一个容易让 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
造成任何影响。推荐阅读
评论