Go 结构体方法中,有一个很重要的点就是值传递和引用传递,我们通过一个例子来看下什么是值传递、什么是引用传递,二者有什么区别。
我们声明 person 结构体,里边有一个 name 字段,用两种方式实现 SetName 方法,分别是值传递和引用传递。
1 2 3 4 5 6 7 8 9 10 11
type person struct { name string }
func (p person) SetName1(name string) { p.name = name }
func (p *person) SetName2(name string) { p.name = name }
如上,SetName1 就是值传递,SetName2 为引用传递。
在 main 方法中,我们分别调用两个 SetName 方法对 name 进行赋值,并打印每次赋值后的 name 值。
1 2 3 4 5 6 7 8 9
func main() { p := &person{}
p.SetName1("张三") fmt.Println(p.name)
p.SetName2("李四") fmt.Println(p.name) }
执行这个程序得到如下结果:
1 2
李四
可以看到 张三 并没有打印出来,而 李四 打印了出来。
在调用 SetName1 时,实际上是复制了一个新的 person,方法内操作的也是那个新 person 把复制 person 的 name 改为了张三,而我们在 main 方法中打印的确是原始 person 的 name 字段。因为我们在初始化 person 时并没有指定 name 的值,所以第一次打印出来的是个空串。
对程序稍作调整,先调用 SetName2 再调用 SetName1:
1 2 3 4 5 6 7 8 9
func main() { p := &person{}
p.SetName2("李四") fmt.Println(p.name)
p.SetName1("张三") fmt.Println(p.name) }
这时输出的结果为:
1 2
李四 李四
第一次调用后,p 结构体指针中 name 的值已经被改为了 李四,接下来我们调用 SetName1 时,因为是复制了一个新的 person,并没有影响之前的 person,所以打印结果还是 李四。