Golang做继承的时候,会有结构体嵌套,出现了两种定义的写法:
type Animal struct {//父类
name string
}
type Dog struct {//子类
Feet int8
Animal //父类结构体
}
type DogWithInnerPointer struct {//子类
Feet int8
*Animal //父类结构体的指针
}
差异在于在 对象值传递的时候 方法内 对象字段的修改:
如果是普通字段,函数体内修改不会对原对象有影响;
如果是指针字段,则会影响原对象的字段。
func main() {
d := &Dog{
Feet: 4,
Animal: Animal{
name: "改名前",
},
}
d2 := &DogWithInnerPointer{
Feet: 4,
Animal: &Animal{ //注意嵌套的是结构体指针
name: "改名前",
},
}
d2.getName()
d.getName()
fmt.Println(d.Feet)
fmt.Println(d2.Feet)
dog1Field(*d)
dog2Field(*d2)
d.getName()
d2.getName()
fmt.Println(d.Feet)
fmt.Println(d2.Feet)
}
func dog1Field(dog Dog) {
dog.name = "改名后"
dog.Feet = 23
}
func dog2Field(dog DogWithInnerPointer) {
dog.name = "改名后"
dog.Feet = 23
}
注意看到最后两个函数接受的是对象的副本!
结果如下,关键看 结果的5、6行。
Animal的名字是改名前
Animal的名字是改名前
4
4
Animal的名字是改名前
Animal的名字是改名后
4
4
但是如果函数是传指针的话,结果又不一样了。
同样的重点看最后两个函数的形参!
func main() {
d := &Dog{
Feet: 4,
Animal: Animal{
name: "改名前",
},
}
d2 := &DogWithInnerPointer{
Feet: 4,
Animal: &Animal{ //注意嵌套的是结构体指针
name: "改名前",
},
}
d2.getName()
d.getName()
fmt.Println(d.Feet)
fmt.Println(d2.Feet)
dog1Field(d)
dog2Field(d2)
d.getName()
d2.getName()
fmt.Println(d.Feet)
fmt.Println(d2.Feet)
}
func dog1Field(dog *Dog) {
dog.name = "改名后"
dog.Feet = 23
}
func dog2Field(dog *DogWithInnerPointer) {
dog.name = "改名后"
dog.Feet = 23
}
函数的形参是指针的话,不论字段是不同字段,还是指针字段,都会对原对象做出修改。
结果如下:
Animal的名字是改名前
Animal的名字是改名前
4
4
Animal的名字是改名后
Animal的名字是改名后
23
23
总结:
函数 值传递的时候 是将对象拷贝一份传入函数体内,对象的普通字段,和指针字段也是副本,所以修改 普通字段的副本不会对原对象字段有影响,而修改指针对象的副本所指向的地址中的值却会对原对象有影响。归根结底是指针和指针的副本指向的都是同一块地址。
而当函数是引用传递的时候(传对象的指针),修改的就是原对象本身了。因为这个指针指向的就是原对象的地址。