Take the address of the value inside the interface

How to get the address of a value inside an interface?

I have a structure stored in the interface in the 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 happening? Since the structure is stored in the interface, why can't I get a pointer to it?

+4
source share
4 answers

To understand why this is not possible, it is useful to think about what an interface variable actually is. An interface value takes two words, the first of which describes the type of value contained, and the second either (a) contains the contained value (if it is placed inside the word), or (b) a pointer to the storage for the value (if the value does not fit inside the word).

It is important to note that (1) the contained value belongs to the interface variable, and (2) the memory for this value can be reused when a new value is assigned to the variable. Knowing this, consider the following code:

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

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

If you need a pointer to the structures that you store in the list, then one option would be to save pointers to the structures in the list, and not to the struct values ​​directly. Alternatively, you can pass *list.Element values ​​as references to the structures they contain.

+5
source

In a first approximation: you cannot do this. Even if you could, p yourself had to be of type interface{} and would not be too useful - you cannot directly dereference it then.

Mandatory question: what problem are you trying to solve?

Last but not least, interfaces define behavior, not structure. Using the interface underlying the type of implementation directly in the general case violates the interface contract, although there may not be general legal cases for it. But they are already filed for a finite set of statically known types using an operator .

+2
source

A type statement is an expression that leads to two values. Taking the address in this case would be ambiguous.

 p, ok := el.Value.(retry) if ok { // type assertion successful // now we can take the address q := &p } 

From the comments:

Note that this is a pointer to a copy of the value, not a pointer to the value itself.

- James Henstridge

Thus, the solution to the problem is simple; save the pointer in the interface, not the value.

+2
source

Get a pointer to an interface value?

Is there a way, given an interface type variable, to get a pointer to the value stored in the variable?

It's impossible.

Rob Pike

Interface values ​​are not necessarily addressable. For instance,

 package main import "fmt" func main() { var i interface{} i = 42 // cannot take the address of i.(int) j := &i.(int) fmt.Println(i, j) } 

Address Operators

For operand x of type T, the address operation & x creates a pointer of type * T to x. The operand must be addressable, i.e. either a variable, a pointer pointer, or a fragment indexing operation; or field selector of an address structural operand; or array indexing operation of the address array. As an exception to the targeting requirement, x can also be a composite literal.

Literature:

Interface Types

Enter Claims

Move data structures: interfaces

Go interfaces

+2
source

All Articles