我有一个带有 *int64
字段的结构类型。
type SomeType struct {
SomeField *int64
}
在我的代码中的某个时刻,我想声明一个文字(比如,当我知道说的值应该是 0,或者指向 0 时,你明白我的意思)
instance := SomeType{
SomeField: &0,
}
…除了这不起作用
./main.go:xx: cannot use &0 (type *int) as type *int64 in field value
所以我试试这个
instance := SomeType{
SomeField: &int64(0),
}
…但这也行不通
./main.go:xx: cannot take the address of int64(0)
我该怎么做呢?我能想出的唯一解决方案是使用占位符变量
var placeholder int64
placeholder = 0
instance := SomeType{
SomeField: &placeholder,
}
注意: &0
语法在 *int 而不是 *int64
时工作 _正常_。编辑:不,它没有。为此表示歉意。
编辑:
显然我的问题含糊不清。我正在寻找一种方法来 逐字说明 a *int64
。这可以在构造函数内部使用,或者声明文字结构值,甚至可以作为其他函数的参数。但是辅助函数或使用不同的类型不是我正在寻找的解决方案。
原文由 ThisGuy 发布,翻译遵循 CC BY-SA 4.0 许可协议
Go 语言规范( 地址运算符)不允许获取数字常量的地址(不是非 类型 常量或 类型 常量的地址)。
有关为什么不允许这样做的原因,请参阅相关问题: Find address of constant in go 。一个类似的问题(同样不允许取其地址): How can I store reference to the result of an operation in Go?
0) 通用解决方案(来自 Go 1.18)
Go 1.18 中添加了泛型。这意味着我们可以创建一个单一的通用
Ptr()
函数,该函数返回指向我们传递给它的任何值的指针。希望它将被添加到标准库中。在那之前,您可以使用github.com/icza/gog
,gog.Ptr()
功能(披露:我是作者)。这是它的样子:
测试它:
这将输出(在 Go Playground 上尝试):
您的其他选项(在 Go 1.18 之前)(在 Go Playground 上尝试所有选项):
1) 与
new()
您可以简单地使用内置
new()
函数来分配一个新的零值int64
并获取其地址:但请注意,这只能用于分配和获取指向任何类型的零值的指针。
2) 辅助变量
最简单且推荐用于非零元素的是使用可以获取其地址的辅助变量:
3)具有辅助功能
注意: 获取指向非零值指针的辅助函数在我的
github.com/icza/gox
库中可用,在gox
包中,因此您不必将这些添加到所有您需要的项目。或者如果你多次需要这个,你可以创建一个辅助函数,它分配并返回一个
*int64
:并使用它:
请注意,我们实际上没有分配任何东西,Go 编译器在我们返回函数参数的地址时这样做了。 Go 编译器执行逃逸分析,如果局部变量可能逃逸函数,则在堆上(而不是堆栈)分配局部变量。有关详细信息,请参阅 在 Go 函数中返回局部数组的一部分安全吗?
4) 单行匿名函数
或者作为(更短的)替代方案:
5) 带slice字面量,索引取地址
如果您希望
*SomeField
不是0
,那么您需要一些可寻址的东西。你仍然可以这样做,但这很丑陋:
这里发生的是
[]int64
切片是用文字创建的,具有一个元素(5
)。并且它被索引(第 0 个元素)并获取第 0 个元素的地址。在后台[1]int64
的数组也将被分配并用作切片的支持数组。所以这里有很多样板文件。6) 使用辅助结构文字
让我们检查可寻址性要求的例外情况:
这意味着获取复合文字的地址,例如结构文字是可以的。如果这样做,我们将分配结构值并获得指向它的指针。但如果是这样,另一个要求将对我们可用: “可寻址结构操作数的字段选择器” 。因此,如果结构文字包含类型为
int64
的字段,我们也可以获取该字段的地址!让我们看看这个选项的实际效果。我们将使用这个包装器结构类型:
现在我们可以这样做:
请注意,这
意思如下:
但是我们可以省略“外部”括号,因为地址运算符
&
应用于 选择器表达式 的结果。另请注意,在后台会发生以下情况(这也是一种有效的语法):
7) 使用助手匿名结构文字
原理与案例 #6 相同,但我们也可以使用匿名结构文字,因此不需要帮助器/包装器结构类型定义: