Go 将接口{}转换为结构

Go 将接口{}转换为结构,go,struct,interface,casting,type-conversion,Go,Struct,Interface,Casting,Type Conversion,我在一个模块中具有以下结构: 类型事件结构{ 名称字符串`json:“名称”` 版本字符串`json:“版本”` 有效负载接口{}`json:“有效负载”` } 目标是,我可以接受任意结构作为Payload,并使用json.Marshal和一些消息服务将类型为Event的最终结构作为json序列化字符串发送 但是,当我在另一个项目中尝试json.Unmarshal时,我无法访问Event.Payload中的字段,因为Go显然不知道它的最终类型 我试着用这样的方法: 类型EventPayload

我在一个模块中具有以下结构:

类型事件结构{
名称字符串`json:“名称”`
版本字符串`json:“版本”`
有效负载接口{}`json:“有效负载”`
}
目标是,我可以接受任意结构作为
Payload
,并使用
json.Marshal
和一些消息服务将类型为
Event
的最终结构作为json序列化字符串发送

但是,当我在另一个项目中尝试
json.Unmarshal
时,我无法访问
Event.Payload
中的字段,因为Go显然不知道它的最终类型

我试着用这样的方法:

类型EventPayload struct{
名称字符串`json:“名称”`
}
// ...
事件:=&events.event{}
event.Payload=&EventPayload{}
如果err:=json.Unmarshal(msg.Data,事件);呃!=零{
返回错误
}
event.Payload.Name//不起作用:“类型接口{}没有字段或方法状态”
然而,Go仍然认为,
event.Payload
是一个
接口{}

在这种情况下,如何判断Go的结构类型正确

在这种情况下,如何判断Go的结构类型正确


你不能。这不是编码/json.Unmarshal的工作方式。您必须将其解组为适当的类型或其他类型,或者使用json.Raw消息并进行第二次解组或诸如此类的操作,但它们的处理方式根本不起作用。

您可以完全按照您所描述的方式进行,只需使用类型断言即可恢复基础类型
json.Unmarshal
,提供了一个带有预填充具体类型的
接口{}
字段,将使用该具体类型

event := &Event{}
event.Payload = &EventPayload{}
msg := []byte(`{"Name": "foo", "Version": "1", "Payload": {"Name": "bar"}}`)

if err := json.Unmarshal(msg, event); err != nil {
    panic(err)
}

pl := event.Payload.(*EventPayload)
fmt.Println(pl.Name)

工作示例(稍微修改为在操场上运行):

对于JSON对象,
Event.Payload
中的值将是
map[string]interface{}
类型,对于JSON数组,
[]interface{}
类型。不能将其强制转换或类型断言为任何其他类型。如果
接口{}
值确实包含该类型的值,则只能从该接口{}值中键入并断言
结构。类型断言不会转换值,也不会神奇地创建新值。
Unmarshal
不会创建基于JSON的类型。它将解组为您给定的类型。您是否希望解组接收端的任何有效负载?为什么不直接将
解压成正确的类型?@super这不是意味着,我必须复制
事件
-struct的原始代码,只是为
有效负载
-field使用不同的类型?我的目标是让
事件
尽可能通用,并重用我以前编写的代码。作为一般性评论:我不认为这个问题有那么糟糕!很抱歉,如果这个问题表明我缺乏理解,那就从总体上说。@TimHilt在
封送处理
方面,它可以保持通用性,但是如果你想将json转换成适当的类型,你需要将代码的这一部分分离出来,并对每种类型的
有效负载使用不同的结构,是的。哦,因此,我只是错过了最后的类型断言!这对我来说是一个有趣且非常重要的见解。非常感谢你。我可以确认,它在我的应用程序中有效。:)只是出于兴趣;为什么在这个问题上我会得到这么多的反对票?我没有想到,一开始这是一场糟糕的比赛,而现在,我知道我离得太近了,我更不理解落选。这可能是坏习惯还是错误地使用围棋?