Golang 结构体、指针、接口实现笔记

对函数来说,参数为 struct、*struct

首先定义struct cat如下
type Cat struct { name string }

并声明如下两个函数
func changeName1(c Cat, name string) { c.name = name }func changeName2(c *Cat, name string) { c.name = name }

func main() { c := Cat{"aaa"} changeName1(c, "bbb") fmt.Println(c) changeName2(&c, "ccc") fmt.Println(c) } // 输出结果 // {aaa} // {ccc}

结论:
  • 对于函数而言,参数中 结构体和结构体指针 是完全两个类型,会发生重载。
  • 结构体参数会完全复制一份,包括结构体内部的字段。
  • 结构体指针参数会将指针完全复制一份,结构体内的字段还是会公用。
对方法来说,接收者为struct、 *struct
func (c Cat) sayHello() { fmt.Printf("hello everyone, i am %s", c.name) }func (c Cat) changeName(name string) { fmt.Printf("i am %s, change my name to %s\n", c.name, name) c.name = name fmt.Printf("cat指针:%p, cat.name指针:%p\n", &c, &(c.name)) }func (c *Cat) changeName2(name string) { fmt.Printf("i am %s, change my name to %s\n", c.name, name) c.name = name fmt.Printf("cat指针:%p, cat.name指针:%p\n", &c, &(c.name)) }

func main() { c := Cat{"aaa"} fmt.Printf("cat指针:%p, cat.name指针:%p\n", &c, &(c.name)) (&c).changeName2("bbb") fmt.Println(c) } // 代码输出 // cat指针:0xc0000461f0, cat.name指针:0xc0000461f0 // i am aaa, change my name to bbb // cat指针:0xc000006030, cat.name指针:0xc0000461f0 // {bbb}

结论:
  • 方法的接收者为指针或者对象,表现形式与 函数的参数为指针或对象 基本一致
  • 不管是指针还是对象,均会将接收者复制一份
接口的指针实现和值实现
type Animal interface { sayHello() }func (c *Cat) sayHello() { fmt.Printf("hello everyone, i am %s", c.name) }

结论:
  • 值实现的接口,可以通过值或者指针 对接口类型变量赋值
  • 指针实现的接口,只能通过指针 对接口类型的变量赋值。
分析:
func main () { var an Animal = &Cat{"aaa"} an.sayHello() }

【Golang 结构体、指针、接口实现笔记】上述声明语句,其实包含两个过程:
  1. 初始化Cat结构体变量。
  2. 将Cat对象,转换成接口类型,此处需要进行一次拷贝,接口中持有了对象。
  3. 值对象赋值给指针实现的接口时,先发生一次拷贝,再取指针,取到的指针不是真实地址,故无法进行转换。

    推荐阅读