无法理解以下行为.差异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}
}
Run Code Online (Sandbox Code Playgroud)
这里到底发生了什么?
这都是关于值与指针的使用和赋值.
在这两种情况下,都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
Run Code Online (Sandbox Code Playgroud)
如您所见:d1指向的内存中的地址已更改.您正在将值存储0x10410020在地图中,因此即使您更改p1为指向另一个地址,地图内的指针仍指向原始位置.
指针看起来像:
m["d1"] -----> data{1}
d1 -----> data{2}
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
由于此地址0x10410028是您在地图中存储的地址,因此它指向d2分配时更改的值.
这个指针看起来像(它们都是指向相同内存区域的指针.抱歉,在ascii中绘制箭头很难):
m["d2"] -----\
data{2}
d2 -----/
Run Code Online (Sandbox Code Playgroud)