Golang中获取结构体指针的方法探讨
Golang中获取结构体指针的方法探讨 请参考以下代码示例(包含编译错误)
问题: 为什么我可以获取结构体变量的地址(见A),但不能获取构造函数返回值的地址(见B), [编辑] 见C和D——它们获取结构体字面量的地址并且编译无误
package main
import "fmt"
type A struct { a int }
func NewA(a int) A { return A{a: a} }
func main() {
a := NewA(10)
aa_1 := &a // A. 编译通过
// 编译错误:无效操作:无法获取 NewA(20) 的地址(类型为 A 的值)
aa_2 := &(NewA(20)) // B. 为什么这行不通?
aa_3 := &(struct{ int }{100}) // C. 编译通过
aa_4 := &(A{100}) // D. 编译通过
fmt.Println(aa_1, aa_2, aa_3, aa_4)
}
更多关于Golang中获取结构体指针的方法探讨的实战教程也可以访问 https://www.itying.com/category-94-b0.html
3 回复
你好 @globalflea,
返回值没有地址。它存在于调用栈上,该栈在函数返回给调用者后会被清理。因此,你必须将其赋值给一个变量(即将其存储在一个更持久的位置),以便为其提供一个代码可以引用的地址。
这是一个关于Go语言地址操作符(&)使用限制的问题。根据Go语言规范,地址操作符只能应用于以下情况:
- 可寻址的值(变量、指针解引用、切片索引、结构体字段选择等)
- 复合字面量(如结构体、数组、切片、映射字面量)
在你的代码中:
// A: 编译通过 - a 是一个变量,可寻址
a := NewA(10)
aa_1 := &a
// B: 编译错误 - NewA(20) 是函数调用返回值,不是可寻址的值
aa_2 := &(NewA(20))
// C: 编译通过 - 结构体字面量是复合字面量
aa_3 := &(struct{ int }{100})
// D: 编译通过 - 结构体字面量是复合字面量
aa_4 := &(A{100})
关键区别在于:函数返回值不是可寻址的值,而复合字面量可以直接取地址。
如果你需要获取构造函数返回值的地址,有以下几种方法:
方法1:先赋值给变量
temp := NewA(20)
aa_2 := &temp
方法2:修改构造函数返回指针
func NewAPtr(a int) *A { return &A{a: a} }
aa_2 := NewAPtr(20)
方法3:使用结构体字面量(如你的C和D所示)
aa_2 := &A{100}
方法4:使用匿名函数(虽然不推荐,但技术上可行)
aa_2 := func() *A {
temp := NewA(20)
return &temp
}()
Go语言这样设计是为了避免以下问题:
- 函数返回值可能存储在临时位置,取地址可能导致悬垂指针
- 保持语言简单性和一致性
- 避免编译器实现复杂性
对于复合字面量,编译器可以直接在堆上分配内存并返回其地址,这是语言规范明确允许的。

