一个容易让 gopher 理解不当的小细节

1type S string
2p := &S{"test"}
S 对象是 string 的别名,它是不可寻址的,编译器会返回 cannot take the address of S("test") 的错误。因此,将例子改为如下所示。1 type S struct {
2 s string
3 }
4 p := &S{"test"}
5 c := p
6 p = nil
7 fmt.Println(p, c)
1<nil> &{test}
p ,c 却没有变化?问题讨论
1 type S struct {
2 s string
3 }
4 p := &S{"test"}
5 c := p
6 fmt.Printf("p指向的地址:%p c指向的地址:%p\n", p, c)
7 fmt.Printf("p本身的地址:%p c本身的地址:%p\n", &p, &c)
8 p = nil
9 fmt.Println(p, c)
1p指向的地址:0xc00008e1e0 c指向的地址:0xc00008e1e0
2p本身的地址:0xc0000ae018 c本身的地址:0xc0000ae020
3<nil> &{test}

p 和 c 都是指向同一块内存的 S 类型指针对象,p = nil 的操作,不是修改它指向地址中的内容,而是修改它的指向,因此 p 的指向变化,不会对 c 造成任何影响。p = nil 修改为 p.s = "sss" ,即代码如下1 type S struct {
2 s string
3 }
4 p := &S{"test"}
5 c := p
6 p.s = "sss"
7 fmt.Println(p, c)
1&{sss} &{sss}

p 对指向地址的内容做了修改,此修改同时影响到了 c 。总结
p 和 c 都是 S 类型的指针对象,它们对同一个指向内容的修改会相互影响。但是,如果是它们的指向发生变化,那么 p 与 c 将不再存在任何关系,它们的内容修改将不再相互影响。所以,如果将上文中 p = nil 修改为 p = &S{"sss"},它同样不会对 c 造成任何影响。推荐阅读
评论
