指向与保存类型接口的指针 [英] Pointer to interface with saving type

查看:221
本文介绍了指向与保存类型接口的指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

解释我的问题的最简单方式是该代码

  var i interface {} //我无法更改它。实际上,这是一个函数,
i = Item {10} //接收接口{},它包含对象(不是指向对象的指针!)

fmt.Printf(%T% (i。(NextValuer).NextVal())//不会编译
i =& i
fmt。 Printf(%T%v \ n,i,i)//这里是指向interface {}(不是Item)的指针
// fmt.Println(i。(NextValuer).NextVal() )// panics
// fmt.Println(i。(* NextValuer).NextVal())//不会编译

但是,如果我尝试设置指向Item的指针,代码有效:

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

但是我的函数接收的是对象,而不是指向它的指针。我可以得到它的类型(第一个 fmt.Printf )。但是当我尝试制作指针时,我收到了指向 interface {} 的指针,而不是我的对象( Item )。



我可以让这个对象的指针调用 NextVal ?或者可能是其他方式来做到这一点

解决方案

切勿使用指向接口的指针。如果你需要一个指针来调用带有指针接收器的方法,那么指针就是你必须放入接口{}



如果您已在接口{} 中具有值,您想在其中调用带有指针接收器的方法,则需要为该接口创建一个可寻址副本值。

您试图用 i =& i 完成的操作可能是:

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

这将创建原始 Item 的可寻址副本,然后将指向该副本的指针放入。请注意,这永远不会改变原始项目的值



如果您不知道类型可以在界面{} 中,您可以使用反映制作该值的副本:



<$ p $ ($ i
v:= reflect.ValueOf(i)

//创建一个指向与我
n:= reflect.New(v.Type())
相同类型的新值的指针//设置新值为i
n。 Elem()。Set(v)

//获取新指针作为接口,并调用NextVal
fmt.Println(NextVal:,n.Interface()。(NextValuer ).NextVal())

//这也可以被赋予另一个接口{}
i = n.Interface()
nv,ok:= i。(NextValuer)
fmt.Printf(我是NextValuer:%t\\\
NextVal:%d\\\
,ok,nv.NextVal())
}

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

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

解决方案

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

这篇关于指向与保存类型接口的指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆