我如何在 Go 中做一个文字 *int64? [英] How do I do a literal *int64 in Go?

查看:36
本文介绍了我如何在 Go 中做一个文字 *int64?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a struct type with a *int64 field.

type SomeType struct {
    SomeField *int64
}

在我的代码中的某个时刻,我想声明一个字面量(比如,当我知道该值应该是 0,或者指向 0 时,你知道我的意思)

At some point in my code, I want to declare a literal of this (say, when I know said value should be 0, or pointing to a 0, you know what I mean)

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)

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

How do I do this? The only solution I can come up with is using a placeholder variable

var placeholder int64
placeholder = 0

instance := SomeType{
    SomeField: &placeholder,
}

注意:&0 语法在使用 *int 而不是 *int64很好. 不,不是.对此表示抱歉.

Note: the &0 syntax works fine when it's a *int instead of an *int64. no it does not. Sorry about this.

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

Aparently there was too much ambiguity to my question. I'm looking for a way to literally state a *int64. This could be used inside a constructor, or to state literal struct values, or even as arguments to other functions. But helper functions or using a different type are not solutions I'm looking for.

推荐答案

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

The Go Language Specification (Address operators) does not allow to take the address of a numeric constant (not of an untyped nor of a typed constant).

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

The operand must be addressable, that is, either a variable, pointer indirection, or slice indexing operation; or a field selector of an addressable struct operand; or an array indexing operation of an addressable array. As an exception to the addressability requirement, x [in the expression of &x] may also be a (possibly parenthesized) composite literal.

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

For reasoning why this isn't allowed, see related question: Find address of constant in go. A similar question (similarly not allowed to take its address): How can I store reference to the result of an operation in Go?

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

Your options (try all on the Go Playground):

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

You can simply use the builtin new() function to allocate a new zero-valued int64 and get its address:

instance := SomeType{
    SomeField: new(int64),
}

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

But note that this can only be used to allocate and obtain a pointer to the zero value of any type.

对于非零元素,最简单和推荐的是使用一个可以获取地址的辅助变量:

Simplest and recommended for non-zero elements is to use a helper variable whose address can be taken:

helper := int64(2)
instance2 := SomeType{
    SomeField: &helper,
}

3) 带辅助功能

注意:获取指向非零值的指针的辅助函数在我的 github.com/icza/gox 库,位于 gox 包,因此您不必将它们添加到您需要的所有项目中.

3) With helper function

Note: Helper functions to acquire a pointer to a non-zero value are available in my github.com/icza/gox library, in the gox package, so you don't have to add these to all your projects where you need it.

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

Or if you need this many times, you can create a helper function which allocates and returns an *int64:

func create(x int64) *int64 {
    return &x
}

并使用它:

instance3 := SomeType{
    SomeField: create(3),
}

注意,我们实际上没有分配任何东西,Go 编译器在我们返回函数参数的地址时这样做了.Go 编译器执行转义分析,并在堆(而不是堆栈)上分配可能对函数进行转义的局部变量.详情见在 Go 函数中返回局部数组的切片安全吗?

Note that we actually didn't allocate anything, the Go compiler did that when we returned the address of the function argument. The Go compiler performs escape analysis, and allocate local variables on the heap (instead of the stack) if they may escape the function. For details, see Is returning a slice of a local array in a Go function safe?

instance4 := SomeType{
    SomeField: func() *int64 { i := int64(4); return &i }(),
}

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

Or as a (shorter) alternative:

instance4 := SomeType{
    SomeField: func(i int64) *int64 { return &i }(4),
}

5) 使用切片字面量、索引和取地址

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

5) With slice literal, indexing and taking address

If you would want *SomeField to be other than 0, then you need something addressable.

你仍然可以这样做,但这很丑陋:

You can still do that, but that's ugly:

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

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

What happens here is an []int64 slice is created with a literal, having one element (5). And it is indexed (0th element) and the address of the 0th element is taken. In the background an array of [1]int64 will also be allocated and used as the backing array for the slice. So there is a lot of boilerplate here.

让我们来看看可寻址性要求的例外情况:

Let's examine the exception to the addressability requirements:

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

As an exception to the addressability requirement, x [in the expression of &x] may also be a (possibly parenthesized) composite literal.

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

This means that taking the address of a composite literal, e.g. a struct literal is ok. If we do so, we will have the struct value allocated and a pointer obtained to it. But if so, another requirement will become available to us: "field selector of an addressable struct operand". So if the struct literal contains a field of type int64, we can also take the address of that field!

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

Let's see this option in action. We will use this wrapper struct type:

type intwrapper struct {
    x int64
}

现在我们可以:

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

注意这个

&(&intwrapper{6}).x

表示如下:

& ( (&intwrapper{6}).x )

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

But we can omit the "outer" parenthesis as the address operator & is applied to the result of the selector expression.

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

Also note that in the background the following will happen (this is also a valid syntax):

&(*(&intwrapper{6})).x

7) 带有辅助匿名结构体

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

7) With helper anonymous struct literal

The principle is the same as with case #6, but we can also use an anonymous struct literal, so no helper/wrapper struct type definition needed:

instance7 := SomeType{
    SomeField: &(&struct{ x int64 }{7}).x,
}

这篇关于我如何在 Go 中做一个文字 *int64?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆