将接口{}转换为结构

Cast interface{} to struct

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

type Event struct {
    Name    string      `json:"name"`
    Version string      `json:"version"`
    Payload interface{} `json:"payload"`
}

目标是,我可以接受任意结构作为 Payload 并将类型 Event 的最终结构作为 json 序列化字符串发送,使用 json.Marshal 和一些消息服务。

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

我试过用这样的东西:

type EventPayload struct{
    Name string `json:"name"`
}

// ...

event := &events.Event{}
event.Payload = &EventPayload{}

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

event.Payload.Name  // Won't work: "type interface{} has no field or method Status"

然而,Go 仍然认为 event.Payload 是一个 interface{}

在这种情况下,我如何告诉 Go 正确的结构类型?

How can I tell Go the correct struct-type in this case?

你不能。这不是 encoding/json.Unmarshal 的工作方式。您要么必须解组为正确的类型或其他类型,要么使用 json.Raw 消息并进行第二次解组或诸如此类的事情,但是您采用的方法根本行不通。

您完全可以按照您的描述进行操作,您只需要使用类型断言来获取基础类型即可。 json.Unmarshal,提供一个预填充具体类型的 interface{} 字段, 使用该具体类型。

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)

工作示例(在 playground 中稍微修改为 运行):https://play.golang.org/p/IDXLKeMGw8_1