为什么变量的内联实例化需要显式地将其地址调用指针方法,而对于现有的var,它的含义是什么?

Gna*_*ani 10 go

这种行为有原因吗?我想知道内存级别有什么不同.编译器返回"不能取复合文字的地址",而我可以明确要求它这样做.

继续去操场去游乐场的链接

u := User{"john"}
fmt.Println(u.Name()) //implicit

//fmt.Println(User{"john"}.Name()) //Error: cannot call pointer method on composite literal, cannot take the address of composite literal
fmt.Println((&User{"jim"}).Name()) //explicit

type User struct {
    name string
}

func (u *User) Name() string {
    return u.name
}
Run Code Online (Sandbox Code Playgroud)

Von*_*onC 9

因为在将复合材料分配给变量之前,它是不可寻址的:

操作数必须是可寻址的,即,变量,指针间接或切片索引操作; 或可寻址结构操作数的字段选择器; 或者可寻址数组的数组索引操作.
作为可寻址性要求的例外,x也可以是(可能带括号的)复合文字.

您可以将地址取为User{"jim"}:( (&User{"jim"})文字指针).
但是你不能直接使用User{"jim"}(字面值,而不是分配给变量).
此主题中查看更多内容.


此线程添加到"表达式无法寻址"问题:

取一些东西的地址,直到这个假设点是不可寻址的(一个不会碰巧根据标识符的表达式),在语义上与设置目标指针的解除引用值没有什么不同.
换句话说,以下是等效的:

var x *int
*x = (2 * 3) + 4

var x *int
x = &((2 * 3) + 4)
Run Code Online (Sandbox Code Playgroud)

由于表达式在使用后立即被丢弃,因此其值的地址(通常完全是寄存器驻留,因此实际上没有地址)在任何情况下都是完全没有意义的,并且获取它的唯一好处是address是变量声明中类型推断的语法便利(最多只保存一行):

x := &((2 * 3) + 4)
Run Code Online (Sandbox Code Playgroud)

使任意表达式可寻址的问题:

m := map[int]int{1:2}
x := &m[1]
x = 3
fmt.Println("x is", x, "while m[1] is", m[1])
// will print `x is 3 while m[1] is 2`
Run Code Online (Sandbox Code Playgroud)

简而言之:它是不清楚的(并且几乎不可能调试)你是否正在获取你期望可寻址的地址,或者你正在采用隐式中间变量的地址(这通常是你的不想要).