go 结构体
1 结构体和方法是如何联系的
结构体和方法是通过方法集(method set)联系起来的.方法集是一个特殊的函数指针,它指向结构体类型的方法. 当定义一个结构体类型时,Go语言会为这个类型生成一个方法集
反射来打印对象的方法
type Dog struct {
Age int
Name string
}
func (d Dog) SetName(name string) {
fmt.Println("input::", name)
d.Name = name
}
func (d *Dog) GetName() string {
fmt.Printf("方法内的地址: %p\n", d)
return d.Name
}
func TestStruct(t *testing.T) {
fmt.Println("Dog 类型的 方法")
d := Dog{Age: 2}
v := reflect.TypeOf(d)
for i := 0; i < v.NumMethod(); i++ {
// SetName == func(test.Dog, string) == func
fmt.Println(v.Method(i).Name, "==", v.Method(i).Type, "==", v.Method(i).Type.Kind())
}
fmt.Println("*Dog 类型的方法")
d2 := &Dog{}
v2 := reflect.TypeOf(d2)
for i := 0; i < v2.NumMethod(); i++ {
// 注意有2个func, SetName(*Dog,string) 方法 自动生成了
// 虽然我们只定义了 func SetName(Dog,string) 方法
// GetName == func(*test.Dog) string == func
// SetName == func(*test.Dog, string) == func
fmt.Println(v2.Method(i).Name, "==", v2.Method(i).Type, "==", v2.Method(i).Type.Kind())
}
}
重要结论
注意 编译器为 Dog 类型的 Shout方法 生成了 对应 *Dog类型 的Shout方法
2 结构体方法的实质与参数
Tip
结构体调用方法实际上是函数的第一个参数是结构体
type Dog struct {
Age int
Name string
}
func (d *Dog) GetName() string {
// 与TestStruct2的 &d 地址一样
fmt.Printf("方法内的地址: %p\n", d)
return d.Name
}
func (d Dog) SetName(name string) {
fmt.Println("input::", name)
d.Name = name
}
// 前面通过反射我们看到实际上的方法是这样的
/*
func SetName(d Dog,name string) {
d.Name = name
}
func GetName(d *Dog) string{
return d.Name
}
结构体方法会自动生成一个结构体指针的方法
func SetName(d *Dog,name string) {
d.Name = name
}
*/
Tip
编译器自动生成的 SetName(*Dog,string) 方法 用于接口,我们后续再说