Pointer to an interface with a save type

The shortest way to explain my problem is this code :

var i interface{} // I can't change it. In fact this is a function, i = Item{10} // that receives interface{}, that contain object (not pointer to object!) fmt.Printf("%T %v\n", i, i) // fmt.Println(i.(NextValuer).NextVal()) // won't compile i = &i fmt.Printf("%T %v\n", i, i) // there i is pointer to interface{} (not to Item) // fmt.Println(i.(NextValuer).NextVal()) // panics // fmt.Println(i.(*NextValuer).NextVal()) // won't compile 

But if I try to set the pointer to Item on i, the code works:

 i = &Item{10} fmt.Printf("%T %v\n", i, i) fmt.Println(i.(NextValuer).NextVal()) 

But my function gets an object, not a pointer to it. And I can get its type ( fmt.Printf first). But when I try to make a pointer to it, I get a pointer to interface{} , and not to my object ( Item ).

Can I make a pointer to this object to call NextVal ? Or there may be other ways to do this.

-1
source share
1 answer

Never use a pointer to an interface. If you need a pointer to a method call with a pointer receiver, a pointer is what you should put in interface{} .

If you already have a value in interface{} , where you want to call a method with a pointer receiver, you need to make an address copy of this value.

What you are trying to accomplish using i = &i is possible:

 item := i.(Item) i = &item 

This creates an address copy of the original Item , and then places the pointer to that copy in i . Note that this can never change the value of the original Item .

If you do not know the type that may be in interface{} , you can make a copy of the value using "reflect":

 func nextVal(i interface{}) { // get the value in i v := reflect.ValueOf(i) // create a pointer to a new value of the same type as i n := reflect.New(v.Type()) // set the new value with the value of i n.Elem().Set(v) // Get the new pointer as an interface, and call NextVal fmt.Println("NextVal:", n.Interface().(NextValuer).NextVal()) // this could also be assigned another interface{} i = n.Interface() nv, ok := i.(NextValuer) fmt.Printf("i is a NextValuer: %t\nNextVal: %d\n", ok, nv.NextVal()) } 

http://play.golang.org/p/gbO9QGz2Tq

+1
source

All Articles