问题
The shortest way to explain my problem is that 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 pointer to Item to i, code works:
i = &Item{10}
fmt.Printf("%T %v\n", i, i)
fmt.Println(i.(NextValuer).NextVal())
But my function receives object, not pointer to it. And I can get type of it (first fmt.Printf). But when I try to make pointer to it, I receive pointer to interface{}, not to my Object (Item).
Can I make pointer to this object to call NextVal? Or may be other ways to do it
回答1:
Never use a pointer to an interface. If you need a pointer to call a method with a pointer receiver, a pointer is what you must put into the interface{}.
If you have already have value in an interface{} where you want to call a method with a pointer receiver, you need to make an addressable copy of that value.
What you're trying to accomplish with i = &i is probably:
item := i.(Item)
i = &item
This creates an addressable copy of the original Item, and then puts a pointer to that copy into i. Note that this can never change the value of the original Item.
If you don't know the type that can be in the interface{}, you can make a copy of the value with "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
来源:https://stackoverflow.com/questions/34600817/pointer-to-interface-with-saving-type