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 回复

好的,谢谢。

更多关于Golang中获取结构体指针的方法探讨的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


你好 @globalflea

返回值没有地址。它存在于调用栈上,该栈在函数返回给调用者后会被清理。因此,你必须将其赋值给一个变量(即将其存储在一个更持久的位置),以便为其提供一个代码可以引用的地址。

这是一个关于Go语言地址操作符(&)使用限制的问题。根据Go语言规范,地址操作符只能应用于以下情况:

  1. 可寻址的值(变量、指针解引用、切片索引、结构体字段选择等)
  2. 复合字面量(如结构体、数组、切片、映射字面量)

在你的代码中:

// 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语言这样设计是为了避免以下问题:

  1. 函数返回值可能存储在临时位置,取地址可能导致悬垂指针
  2. 保持语言简单性和一致性
  3. 避免编译器实现复杂性

对于复合字面量,编译器可以直接在堆上分配内存并返回其地址,这是语言规范明确允许的。

回到顶部