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

时间:2018-01-27 14:23:40

标签: 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}
}

这里到底发生了什么?

1 个答案:

答案 0 :(得分:5)

这完全是关于值和指针的使用和assignment

在这两种情况下,m[something]都会保存data的地址。 但是,重要的区别在于d1d2

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

如您所见:d1指向的内存中的地址已更改。您将值0x10410020存储在地图中,因此即使您将p1更改为指向另一个地址,地图内的指针仍指向原始位置。

指针看起来像:

m["d1"] -----> data{1}

d1      -----> data{2}

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

由于此地址0x10410028是您在地图中存储的地址,因此它指向d2的值,该值会在分配时更改。

这个中的指针看起来像是(它们指向同一个记忆区域的指针。抱歉,在ascii中绘制箭头很难):

m["d2"] -----\
             data{2}
d2      -----/