如何在Go中使用文字*int64?

Thi*_*Guy 79 struct pointers literals go

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

type SomeType struct {
    SomeField *int64
}
Run Code Online (Sandbox Code Playgroud)

在我的代码中的某个时刻,我想声明一个这样的文字(比如,当我知道所述值应为0,或者指向0时,你知道我的意思)

instance := SomeType{
    SomeField: &0,
}
Run Code Online (Sandbox Code Playgroud)

...除了这不起作用

./main.go:xx: cannot use &0 (type *int) as type *int64 in field value
Run Code Online (Sandbox Code Playgroud)

所以我试试这个

instance := SomeType{
    SomeField: &int64(0),
}
Run Code Online (Sandbox Code Playgroud)

......但这也行不通

./main.go:xx: cannot take the address of int64(0)
Run Code Online (Sandbox Code Playgroud)

我该怎么做呢?我能想出的唯一解决方案是使用占位符变量

var placeholder int64
placeholder = 0

instance := SomeType{
    SomeField: &placeholder,
}
Run Code Online (Sandbox Code Playgroud)

注意:当它是*int而不是a时,&0语法工作正常*int64.编辑:不,不.为此表示歉意.

编辑:

显然,我的问题含糊不清.我正在寻找一种方法来说明一个*int64.这可以在构造函数中使用,或者用于表示文字结构值,或者甚至作为其他函数的参数.但帮助函数或使用不同的类型不是我正在寻找的解决方案.

icz*_*cza 169

Go语言规范(地址运算符)不允许获取数字常量的地址(不是类型的常量,也不是类型常量的地址).

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

为了推理为什么不允许这样做,请参阅相关问题:在go中查找常量的地址.一个类似的问题(同样不允许取其地址):如何在Go中存储对操作结果的引用?

您的选择(在Go Playground尝试所有):

1)有 new()

您可以简单地使用内置new()函数来分配新的零值int64并获取其地址:

instance := SomeType{
    SomeField: new(int64),
}
Run Code Online (Sandbox Code Playgroud)

但请注意,这只能用于分配和获取指向任何类型的零值的指针.

2)使用辅助变量

对于非零元素,最简单和建议使用可以采用其地址的辅助变量:

helper := int64(2)
instance2 := SomeType{
    SomeField: &helper,
}
Run Code Online (Sandbox Code Playgroud)

3)具有辅助功能

或者如果你需要这么多次,你可以创建一个辅助函数,它分配并返回一个*int64:

func create(x int64) *int64 {
    return &x
}
Run Code Online (Sandbox Code Playgroud)

并使用它:

instance3 := SomeType{
    SomeField: create(3),
}
Run Code Online (Sandbox Code Playgroud)

4)具有单行匿名功能

instance4 := SomeType{
    SomeField: func() *int64 { i := int64(4); return &i }(),
}
Run Code Online (Sandbox Code Playgroud)

或者作为(较短的)替代方案:

instance4 := SomeType{
    SomeField: func(i int64) *int64 { return &i }(4),
}
Run Code Online (Sandbox Code Playgroud)

5)使用切片文字,索引和获取地址

如果你想要*SomeField不是0,那么你需要一些可寻址的东西.

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

instance5 := SomeType{
    SomeField: &[]int64{5}[0],
}
fmt.Println(*instance2.SomeField) // Prints 5
Run Code Online (Sandbox Code Playgroud)

这里发生的是一个[]int64切片用文字创建,有一个元素(5).并且它被索引(第0个元素)并且取第0个元素的地址.在后台,[1]int64还将分配一个数组并将其用作切片的后备数组.所以这里有很多样板.

6)使用辅助结构文字

让我们检查可寻址性要求的例外情况:

作为可寻址性要求的一个例外,x[在表达式中&x]也可以是(可能带括号的)复合文字.

这意味着获取复合文字的地址,例如结构文字是可以的.如果我们这样做,我们将分配结构值并获得指针.但如果是这样,我们将可以使用另一个要求:"可寻址结构操作数的字段选择器".因此,如果struct literal包含一个类型的字段int64,我们也可以获取该字段的地址!

让我们看看这个选项的实际效果.我们将使用这个包装结构类型:

type intwrapper struct {
    x int64
}
Run Code Online (Sandbox Code Playgroud)

现在我们可以做到:

instance6 := SomeType{
    SomeField: &(&intwrapper{6}).x,
}
Run Code Online (Sandbox Code Playgroud)

请注意这一点

&(&intwrapper{6}).x
Run Code Online (Sandbox Code Playgroud)

表示以下内容:

& ( (&intwrapper{6}).x )
Run Code Online (Sandbox Code Playgroud)

但是我们可以省略"外部"括号,因为地址运算符&应用于选择器表达式的结果.

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

&(*(&intwrapper{6})).x
Run Code Online (Sandbox Code Playgroud)

7)使用帮助程序匿名struct literal

原理与案例#6相同,但我们也可以使用匿名struct literal,因此不需要helper/wrapper struct type定义:

instance7 := SomeType{
    SomeField: &(&struct{ x int64 }{7}).x,
}
Run Code Online (Sandbox Code Playgroud)

  • @Conslo常量在编译时进行评估.有效的指针值,有效的内存地址仅存在于运行时,因此这与常量不同. (4认同)
  • 这肯定回答了我的问题.但它让我非常沮丧:`&[] int64 {2} [0]`,我觉得基于http://blog.golang.org/constants上的常量描述,这*应该*只是作为`&0 `. (2认同)
  • @rajkamal 只是因为规范不允许。您可以获取复合文字的地址(第一个示例),但不能获取复合文字的字段地址(这未在规范中列出)。请注意,您可以获取结构类型变量的字段地址,但不能获取复合文字的地址(_“可寻址结构操作数的字段选择器”_)。 (2认同)
  • 如果你真的想偷懒,这里有一个包,为每个 go 原语类型提供辅助函数(解决方案#3):https://godoc.org/github.com/mwielbut/pointy (2认同)
  • 请参阅 Go 语言 [“提案:创建指向简单类型的指针的表达式”](https://github.com/golang/go/issues/45624) (2认同)

Val*_*ani 8

如果您不介意使用第三方库,则有一个使用泛型(go 1.18+)的lo.ToPtr()包,它具有以下功能

ptr := lo.ToPtr("hello world")
// *string{"hello world"}
Run Code Online (Sandbox Code Playgroud)


ASH*_*EEV 6

使用返回 int64 变量地址的函数来解决问题。

在下面的代码中,我们使用f接受一个整数并返回一个保存整数地址的指针值的函数。通过使用这种方法,我们可以轻松解决上述问题。

type myStr struct {
    url *int64
}

func main() {
    f := func(s int64) *int64 {
        return &s
    }
    myStr{
        url: f(12345),
    }
}
Run Code Online (Sandbox Code Playgroud)