指针的这种用法有什么区别(a:=&A; a)和(b:= B;&b)

aer*_*ite 1 pointers go

无法理解以下行为.差异d1 := &data{1}; d1d2 := 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)

这里到底发生了什么?

Mar*_*arc 5

这都是关于值与指针的使用和赋值.

在这两种情况下,都m[something]持有一个地址data.然而,重要的区别是什么d1和是什么d2.

d1的类型是*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)

d2的类型是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)