Pointer to interface with saving type

北慕城南 提交于 2019-12-13 08:51:06

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!