By ThisGuy


2015-06-08 18:21:38 8 Comments

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 &0 syntax works fine when it's a *int instead of an *int64. Edit: no it does not. Sorry about this.

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.

2 comments

@icza 2015-06-08 18:28:58

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).

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.

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?

Your options (try all on the Go Playground):

1) With new()

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.

2) With helper variable

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) With helper function

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
}

And using it:

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

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?

4) With a one-liner anonymous function

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) 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

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:

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

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
}

And now we can do:

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

Note that this

&(&intwrapper{6}).x

means the following:

& ( (&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) 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,
}

@Ryan Haining 2015-06-08 18:31:49

this is functionally different from the last example in the question with the placeholder, since two dfferent instance objects would point to two different int64s. But it does seems to meet OPs intent adequately

@ThisGuy 2015-06-08 18:38:06

this definitely answers my question. But it makes me quite upset: &[]int64{2}[0], I feel like based on the description of constants at blog.golang.org/constants this should just work as &0.

@icza 2015-06-08 19:05:11

@RyanHaining And what would happen if it would work like the same address would be assigned? If two different instance objects would point to the same int64 and one would modify the pointed object, both would change. And what if now you use the same literal to create a 3rd instance? The same address would now point to a different int64 value... so a different address should be used, but then why use the same in the case of the first 2?

@Ryan Haining 2015-06-08 19:10:04

@icza you typically wouldn't want them pointing to the same object, I'm not saying you would. I'm just pointing out the difference.

@icza 2015-06-08 19:10:57

@Conslo Constants are evaluated at compile time. A valid pointer value, a valid memory address only exists at runtime, so this is not the same as constants.

@ThisGuy 2015-06-08 19:30:16

@icza yea I guess you're right

@Rajkamal Subramanian 2017-11-20 21:59:51

@icza, i have a question about the selector used in method#6. I have the question mentioned in the playground url play.golang.org/p/U9jqOYA6EP. (comment allows only few chars)

@icza 2017-11-21 07:59:26

@rajkamal Simply because the spec does not allow it. You can take the address of a composite literal (your first example), but you can't take the address of a field of a composite literal (this is not listed in the spec). Note that you can take however the address of a field of a variable of struct type, but not that of a composite literal ("field selector of an addressable struct operand").

@tom10271 2018-04-13 03:31:57

It is pathetic for any Go developer to get a string pointer like these...

@mwielbut 2018-12-24 16:46:33

If you want to be really lazy, here is a package that provides the helper functions (solution #3) for each go primitive type: godoc.org/github.com/mwielbut/pointy

@ASHWIN RAJEEV 2018-09-21 10:03:55

Use a function which return an address of a int64 variable will solve the problem.

In the below code we use a function f which accepts integer and return a pointer value which holds the address of the integer. By using this method we can easily solve the above problem.

 type myStr struct {
        url *int64
    }

    func main() {

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

Related Questions

Sponsored Content

2 Answered Questions

[SOLVED] Value receiver vs. pointer receiver

  • 2015-01-05 07:54:11
  • Chrisport
  • 17819 View
  • 85 Score
  • 2 Answer
  • Tags:   function pointers go

6 Answered Questions

[SOLVED] Swift and mutating struct

5 Answered Questions

[SOLVED] Empty set literal?

  • 2011-05-25 20:18:55
  • Johan Råde
  • 178997 View
  • 411 Score
  • 5 Answer
  • Tags:   python set literals

2 Answered Questions

[SOLVED] Using reflect, how do you set the value of a struct field?

4 Answered Questions

2 Answered Questions

[SOLVED] Golang: JSON: How do I unmarshal array of strings into []int64

  • 2018-03-21 20:02:56
  • Vojtech Vitek
  • 6033 View
  • 1 Score
  • 2 Answer
  • Tags:   json go

1 Answered Questions

[SOLVED] Manipulate struct field when using interface

6 Answered Questions

[SOLVED] How do you express binary literals in Python?

2 Answered Questions

[SOLVED] How to unite two different struct using interface?

0 Answered Questions

Incosistency in composite literals

Sponsored Content