I have a struct type with a *int64
field.
type SomeType struct {
SomeField *int64
}
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,
}
...except this doesn't work
./main.go:xx: cannot use &0 (type *int) as type *int64 in field value
So I try this
instance := SomeType{
SomeField: &int64(0),
}
...but this also doesn't work
./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,
}
Note: the Edit: no it does not. Sorry about this.&0
syntax works fine when it's a *int instead of an *int64
.
Edit:
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.
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).
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?
0) Generic solution (from Go 1.18)
Generics are added in Go 1.18. This means we can create a single, generic
Ptr()
function that returns a pointer to whatever value we pass to it. Hopefully it'll get added to the standard library. Until then, you can usegithub.com/icza/gog
, thegog.Ptr()
function (disclosure: I'm the author).This is how it can look like:
Testing it:
Which will output (try it on the Go Playground):
Your other options (prior to Go 1.18) (try all on the Go Playground):
1) With
new()
You can simply use the builtin
new()
function to allocate a new zero-valuedint64
and get its address:But note that this can only be used to allocate and obtain a pointer to the zero value of any type.
2) With helper variable
Simplest and recommended for non-zero elements is to use a helper variable whose address can be taken:
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 thegox
package, so you don't have to add these to all your projects where you need it.Or if you need this many times, you can create a helper function which allocates and returns an
*int64
:And using it:
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 allocates 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?
4) With a one-liner anonymous function
Or as a (shorter) alternative:
5) With slice literal, indexing and taking address
If you would want
*SomeField
to be other than0
, then you need something addressable.You can still do that, but that's ugly:
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.6) With a helper struct literal
Let's examine the exception to the addressability requirements:
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:
And now we can do:
Note that this
means the following:
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):
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: