Pointers 如何在Go中执行文字*int64?

Pointers 如何在Go中执行文字*int64?,pointers,go,struct,literals,Pointers,Go,Struct,Literals,我有一个带有*int64字段的结构类型 type SomeType struct { SomeField *int64 } 在我的代码中的某个时刻,我想声明一个这样的文字(比如,当我知道所说的值应该是0,或者指向一个0时,你知道我的意思) ……但这不起作用 ./main.go:xx: cannot use &0 (type *int) as type *int64 in field value ./main.go:xx: cannot take the address of

我有一个带有
*int64
字段的结构类型

type SomeType struct {
    SomeField *int64
}
在我的代码中的某个时刻,我想声明一个这样的文字(比如,当我知道所说的值应该是0,或者指向一个0时,你知道我的意思)

……但这不起作用

./main.go:xx: cannot use &0 (type *int) as type *int64 in field value
./main.go:xx: cannot take the address of int64(0)
所以我试试这个

instance := SomeType{
    SomeField: &int64(0),
}
……但这也不起作用

./main.go:xx: cannot use &0 (type *int) as type *int64 in field value
./main.go:xx: cannot take the address of int64(0)
我该怎么做?我能想到的唯一解决方案是使用占位符变量

var placeholder int64
placeholder = 0

instance := SomeType{
    SomeField: &placeholder,
}
注意:
&0
语法在使用*int而不是
*int64
时可以正常工作。编辑:没有。很抱歉

编辑:


我的问题显然有太多模棱两可之处。我正在寻找一种方法,可以直接声明一个
*int64
。这可以在构造函数内部使用,也可以用于声明文本结构值,甚至可以用作其他函数的参数。但是助手函数或使用不同类型的函数并不是我要寻找的解决方案。

Go语言规范()不允许获取数值常量的地址(既不是非类型常量,也不是类型常量)

操作数必须是可寻址的,即变量、指针间接寻址或切片索引操作;或可寻址结构操作数的字段选择器;或可寻址数组的数组索引操作。作为可寻址性要求的例外,
x
[在
&x
]的表达式中]也可以是a(可能带括号)

有关不允许这样做的原因,请参阅相关问题:。类似的问题(同样不允许回答):

您的选项(在上尝试所有选项):

1) 使用
new()
您只需使用内置函数分配一个新的零值
int64
,并获取其地址:

instance := SomeType{
    SomeField: new(int64),
}
但请注意,这只能用于分配和获取指向任何类型的零值的指针

2) 带辅助变量 对于非零元素,最简单且推荐的方法是使用一个helper变量,该变量的地址可以是:

helper := int64(2)
instance2 := SomeType{
    SomeField: &helper,
}
3) 具有辅助函数 注意:用于获取指向非零值指针的帮助函数可在我的库中的软件包中找到,因此您不必将这些函数添加到所有需要的项目中

或者,如果需要多次,可以创建一个helper函数,该函数分配并返回
*int64

func create(x int64) *int64 {
    return &x
}
使用它:

instance3 := SomeType{
    SomeField: create(3),
}
请注意,我们实际上没有分配任何内容,当我们返回函数参数的地址时,Go编译器就这样做了。Go编译器执行转义分析,并在堆(而不是堆栈)上分配局部变量(如果它们可能转义函数)。有关详细信息,请参阅

4) 使用一行匿名函数 或作为(较短的)备选方案:

instance4 := SomeType{
    SomeField: func(i int64) *int64 { return &i }(4),
}
5) 使用切片文字、索引和获取地址 如果希望
*SomeField
不是
0
,则需要可寻址的内容

你仍然可以这样做,但那很难看:

instance5 := SomeType{
    SomeField: &[]int64{5}[0],
}
fmt.Println(*instance2.SomeField) // Prints 5
这里发生的是一个
[]int64
切片是用一个文本创建的,它有一个元素(
5
)。并对其进行索引(第0个元素),并获取第0个元素的地址。在后台,还将分配一个
[1]int64
数组,并将其用作切片的后备数组。所以这里有很多样板

6) 使用helper结构文本 让我们检查一下可寻址性要求的例外情况:

作为可寻址性要求的例外,
x
[在
&x
]的表达式中]也可以是a(可能带括号)

这意味着获取复合文本的地址(例如结构文本)是可以的。如果我们这样做,我们将分配struct值并获得指向它的指针。但如果是这样的话,我们还需要另一个条件:“可寻址结构操作数的字段选择器”。因此,如果struct literal包含类型为
int64
的字段,我们还可以获取该字段的地址

让我们看看这个选项在起作用。我们将使用此包装结构类型:

type intwrapper struct {
    x int64
}
现在我们可以做:

instance6 := SomeType{
    SomeField: &(&intwrapper{6}).x,
}
请注意

&(&intwrapper{6}).x
指以下各项:

& ( (&intwrapper{6}).x )
但是我们可以省略“外”括号,因为地址运算符
&
应用于

还要注意,在后台会发生以下情况(这也是一种有效的语法):

7) 使用helper匿名结构文本 原理与案例#6相同,但我们也可以使用匿名结构文字,因此不需要帮助器/包装器结构类型定义:

instance7 := SomeType{
    SomeField: &(&struct{ x int64 }{7}).x,
}
使用返回int64变量地址的函数来解决此问题。 在下面的代码中,我们使用函数
f
,它接受整数和 返回保存整数地址的指针值。通过使用这种方法,我们可以很容易地解决上述问题


@icza你通常不会希望它们指向同一个对象,我不是说你会。我只是指出不同之处。@Conslo常量是在编译时计算的。一个有效的指针值,一个有效的内存地址只在运行时存在,所以这与常量不同。@icza,我对方法#6中使用的选择器有一个问题。我在操场url中提到了这个问题。(注释只允许几个字符)@rajkamal只是因为规范不允许它。您可以获取复合文字的地址(第一个示例),但不能获取复合文字字段的地址(规范中未列出)。请注意,您可以获取结构类型变量的字段地址,但不能获取复合文字的地址(“可寻址结构操作数的字段选择器”)。如果您真的想偷懒,这里有一个提供帮助函数的包(解决方案#3)对于每个go原语类型:指向int的指针都是不幸的,因为int与指针占用的空间量相同,所以不能节省空间。它只是添加了一个空值,这个值通常比实际值复杂得多。
instance7 := SomeType{
    SomeField: &(&struct{ x int64 }{7}).x,
}
type myStr struct {
    url *int64
}

func main() {
    f := func(s int64) *int64 {
        return &s
    }
    myStr{
        url: f(12345),
    }
}