为了账号安全,请及时绑定邮箱和手机立即绑定

golang 通过反射从接口获取结构

golang 通过反射从接口获取结构

Go
慕虎7371278 2021-11-29 16:13:19
原问题:我正在尝试进行一些反序列化,并且对传入接口时如何访问结构有些困惑。package mainimport (    "fmt"    "reflect")type Robot struct {    Id int}func f(i interface{}) {    v := reflect.ValueOf(i).Elem().FieldByName("Id")    fmt.Println("fields: ", reflect.ValueOf(i).Elem().NumField())     ptr := v.Addr().Interface().(*int)    *ptr = 100}func main() {    robot := Robot{}    var iface interface{} = robot // if I omit this line and pass in robot this works    f(&iface)    fmt.Println(robot.Id) //I want to get here 100}http://play.golang.org/p/y6UN3KZxRB如果您只是直接传入结构,那么播放示例就可以工作,但是因为可以传入任何实现特定接口的东西(在我的示例中,我只是使用空接口)。但是,我无法弄清楚如何将其视为下面的结构。更新:package mainimport (    "fmt"    "reflect")type MessageOne struct {    Header   string `FixedWidth:0,4`    FieldOne string `FixedWidth:"4,4"`    FieldTwo string `FixedWidth:"8,4"`}type MessageTwo struct {    FieldX string `FixedWidth:"X,Y"`    FieldY string `FixedWidth:"X,Y"`}var (    messageMap = map[string]interface{}{        "msg1": MessageOne{FieldOne: "testValueUnchanged"},        "msg2": MessageTwo{},    })我想复制我的结构,从而从这里获得一个可寻址的实例:https : //gist.github.com/hvoecking/10772475所以我想我现在的问题是,是否有一种机制可以访问可寻址/可设置的结构而不必求助于副本?潜在的问题是获取字符串(实际上是字节数组)并且让结构具有必要的信息来有效地反序列化它,而不必编写几十个反序列化函数,这些反序列化函数很难维护。因此,示例问题中没有解决这些示例结构中的标签,但访问结构标签字段将提供偏移量,从中可以从输入字节填充结构。显然我还没有走到那一步。我在这里感到沮丧的部分原因是,我似乎很努力地工作才没有走得太远,而且我不觉得我在这个过程中学到了很多东西。一些额外的游戏编辑让我恢复了我的标签:http : //play.golang.org/p/2DbbWLDKPI
查看完整描述

3 回答

?
弑天下

TA贡献1818条经验 获得超8个赞

您不想传递指向接口的指针,而是希望传递指向结构本身的指针。

robot := &Robot{}
f(robot)

http://play.golang.org/p/owv-Y4dnkl

您分配robot给的那一刻iface,您就创建了该robot值的副本。没有办法获得对robotfrom的引用iface

当您传入时f(&iface),对 的调用reflect.ValueOf(i).Elem()仅返回内部iface值,而不是Robot结构值。


查看完整回答
反对 回复 2021-11-29
?
GCT1015

TA贡献1827条经验 获得超4个赞

在您的原始代码中,使用:


var iface interface{} = &robot

f(iface)

说明

在原始版本中,我们发送的是接口变量的地址(这是机器人的副本)。这会发送一个类型为 interface 的指针,因此反射对机器人的副本起作用。


var iface interface{} = robot

f(&iface)

我们需要做的是为接口变量分配一个robot类型的指针。因此,当我们发送接口时,我们发送的是robot 类型的指针,因此reflect 使用实际的robot 对象而不是副本。


var iface interface{} = &robot

f(iface)


查看完整回答
反对 回复 2021-11-29
?
至尊宝的传说

TA贡献1789条经验 获得超10个赞

您可以使用类型断言。


value, ok := i(Robot)

if ok {

    fmt.Println(value.Id)

}


查看完整回答
反对 回复 2021-11-29
  • 3 回答
  • 0 关注
  • 174 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信