Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Take address of value inside an interface

How do I take the address of a value inside an interface?

I have an struct stored in an interface, in a list.List element:

import "container/list"
type retry struct{}
p := &el.Value.(retry)

But I get this:

cannot take the address of el.Value.(retry)

What's going on? Since the struct is stored in the interface, why can't I get a pointer to it?

like image 770
Matt Joiner Avatar asked Mar 20 '13 08:03

Matt Joiner


1 Answers

To understand why this isn't possible, it is helpful to think about what an interface variable actually is. An interface value takes up two words, with the first describing the type of the contained value, and the second either (a) holding the contained value (if it fits within the word) or (b) a pointer to storage for the value (if the value does not fit within a word).

The important things to note are that (1) the contained value belongs to the interface variable, and (2) the storage for that value may be reused when a new value is assigned to the variable. Knowing that, consider the following code:

var v interface{}
v = int(42)
p := GetPointerToInterfaceValue(&v) // a pointer to an integer holding 42
v = &SomeStruct{...}

Now the storage for the integer has been reused to hold a pointer, and *p is now an integer representation of that pointer. You can see how this has the capacity to break the type system, so Go doesn't provide a way to do this (outside of using the unsafe package).

If you need a pointer to the structs you're storing in a list, then one option would be to store pointers to the structs in the list rather than struct values directly. Alternatively, you could pass *list.Element values as references to the contained structures.

like image 90
James Henstridge Avatar answered Sep 28 '22 09:09

James Henstridge