
go 语言中,函数返回值是临时值(非地址可寻址),无法直接对其使用 & 操作符获取指针;必须先将返回值赋给一个变量,再对该变量取地址。
go 语言中,函数返回值是临时值(非地址可寻址),无法直接对其使用 & 操作符获取指针;必须先将返回值赋给一个变量,再对该变量取地址。
在 Go 中,& 操作符只能作用于地址可寻址(addressable) 的操作数。根据 Go 语言规范,一个值要能被取地址,必须满足以下条件之一:
- 是一个变量(如
var s string中的s); - 是指针解引用(如
p.x,其中p是指向结构体的指针); - 是切片索引表达式(如
s[0]); - 是可寻址结构体的字段选择器(如
v.Field,其中v是变量); - 是可寻址数组的索引操作(如
a[5]); - 或是一个复合字面量(如
&struct{X int}{1},这是唯一允许对临时值取地址的例外)。
而函数调用表达式(如 getAString())的结果是一个纯右值(r-value) —— 它没有内存地址,仅存在于求值瞬间,因此不满足“地址可寻址”要求。
✅ 正确写法(引入中间变量):
func getAString() string {
return "hello"
}
func getAStringPointer() *string {
result := getAString() // result 是局部变量,可寻址
return &result // ✅ 合法:对变量取地址
}
❌ 错误写法(直接对调用结果取地址):
func getAStringPointer() *string {
return &getAString() // ❌ 编译错误:cannot take the address of getAString()
}
⚠️ 注意事项:
- 即使函数返回的是结构体、切片或 map,其返回值本身仍是不可寻址的临时值(除非是复合字面量);
- 若需返回指向返回值的指针,务必显式分配变量(栈上或堆上),Go 编译器会自动决定是否逃逸;
- 不要试图用
&(...)包裹调用来“绕过”限制——这仅对复合字面量有效,对函数调用无效。
? 小结:Go 的设计强调显式性与内存安全。禁止直接对函数返回值取地址,避免了悬空指针和生命周期混淆的风险。看似多了一行代码,实则是对值语义和所有权的清晰表达。











