-2

我今天遇到了一个问题,并且能够快速找到并修复它,但不完全理解为什么 golang 语义是这样的。

我正在使用 Go 1.10。

package main

import "fmt"

type T struct {
    V int
}

var testT = T{}

func main() {
    t := &(*(&testT))
    t.V = 4
    fmt.Println(t, testT) // test.V == t.V -> t == &testT

    t1 := &testT
    t2 := *t1
    t3 := &t2
    t3.V = 5
    fmt.Println(t3, testT) // t3.V == 4 and test.T == 4 -> t3 != &testT
}

输出

&{4} {4}
&{5} {4}

我期望不等于 &testT 所以具有与 t3 相同的语义,但是相反,如果我将中间结果存储在变量中,我看到 &(*(&)) 序列没有相同的语义

我的问题

这种行为的原因是什么?

4

1 回答 1

9

当你这样做时:

t1 := &testT
t2 := *t1
t3 := &t2
t3.V = 5

你取 的地址testT,把它存入t1。然后在下一行中创建了一个的、不同的变量t2,它将具有与t1ortestT不同的内存空间和地址。然后t3将存储这个新的、不同的变量的地址,它独立于t1or testT

当你这样做时:

t := &(*(&testT))

您获取 的地址testT,然后取消引用指针(得到testT“返回”),然后再次获取该值的地址,该地址将成为 的地址testT没有创建新变量。所以t会指向testT

这是正常和合乎逻辑的,没有什么令人惊讶的。规范中的相关部分:地址运算符:

x对于指针类型的操作数,*T指针间接*x表示指向的类型的变量Tx

&testT变量的地址也是如此testT,并将*(&testT)返回testT变量。再次获取其地址将与 相同&testT

可能暗示这一点的是采用复合文字的地址。规范:复合文字:

获取复合文字的地址会生成一个指针,该指针指向使用该文字的值初始化的唯一变量。

当您获取复合文字(例如&image.Point{})的地址时,它确实会在内部创建一个新的匿名变量,并且该匿名变量的地址将是表达式的结果。但是获取变量的地址并不会创建新变量。

于 2018-03-01T16:03:09.310 回答