无法理解以下行为。 d1 := &data{1}; d1
和d2 := data{1}; &d1
的区别。两者都是指针,对吗?但他们的行为却不同。这里发生了什么事
package main
import "fmt"
type data struct {
value int
}
func main() {
m := make(map[string]*data)
d1 := &data{1}
m["d1"] = d1 // Here putting &{1}
d1 = &data{2}
fmt.Println(m["d1"])
// &{1}
d2 := data{1}
m["d2"] = &d2 // Here putting &{1}
d2 = data{2}
fmt.Println(m["d2"])
// &{2}
}
这里到底发生了什么?
这都是关于值和指针的使用和assignment。
在这两种情况下,m[something]
都持有data
的地址。然而,重要的区别是d1
和d2
。
*data
:d1
的值是一个指针。当我们将&data{...}
分配给d1
时,这会将d1
的值更改为指向新结构的指针。
由于您要分配或更改d1
的值,因此地图仍保留旧值。
d1 := &data{1}
fmt.Printf("d1 value: %p\n", d1)
// d1 value: 0x10410020
d1 = &data{2}
fmt.Printf("d1 value: %p\n", d1)
// d1 value: 0x10410024
如您所见:d1
指向的内存中的地址已发生变化。您将值0x10410020
存储在地图中,因此即使您将p1
更改为指向另一个地址,地图内的指针仍指向原始位置。
指针看起来像:
m["d1"] -----> data{1}
d1 -----> data{2}
data
:在d2
的情况下,您存储变量d2
的地址。在赋值时,我们更改d2
的值,但其地址不会更改。
d2 := data{1}
fmt.Printf("d2 address: %p\n", &d2)
// d2 address: 0x10410028
d2 = data{2}
fmt.Printf("d2 address: %p\n", &d2)
// d2 address: 0x10410028
由于此地址0x10410028
是您在地图中存储的地址,因此它指向d2
的值,该值在赋值时更改。
这个指针看起来像(它们都是指向相同内存区域的指针。抱歉,在ascii中绘制箭头很难):
m["d2"] -----\
data{2}
d2 -----/