结构体成员可以接受动态变量吗?

问题描述 投票:0回答:1

我有多个

struct
。我的主要响应结构称为
WsPayload
,它有一个名为
Payload
的成员变量。
Payload
可以是我的
Earthquake
结构或
EventReport
结构。

我的问题:我如何定义我的

WsPayload
Payload 成员变量,以便它可以接受我的两个结构?我可以在 Go 中使用动态变量来完成此任务吗?

我正在构建一个从客户端接收有效负载(JSON 格式)的 websocket。然后我将该消息广播到 websocket 客户端(JSON 格式)。在有效负载中,有一个名为

Etype
的结构体成员,它确定有效负载的类型。它可能是事件或地震有效负载。

type WsPayload struct {
    Action   string              `json: "action"`
    Message  string              `json: "message"`
    Etype    string              `json: "etype"`
    Payload  EventReport         `json: "payload"`.  //<---
    Conn     WebSocketConnection `json: "-"`
}

type Earthquake struct {
    Body     string `json: "body"`
    Location string `json: "location"`
    Rate     int    `json: "rate_earthquake"`
    Date     string `json: "lat"`
    Time     string `json: "lng"`
}

type EventReport struct {
    Title string   `json: "title"`
    Body  string   `json: "body"`
    Date  string   `json: "date"`
    Time  string   `json: "time"`
    Type  string   `json: "type"`
    Id    string   `json: "id"`
    Photo []string `json: "photo"`
}

目前,我一次只能在我的

struct
中定义一个
WsPayload

go
1个回答
0
投票

将该字段声明为类型 any

type WsPayload struct {
    Action  string `json:"action"`
    Message string `json:"message"`
    Etype   string `json:"etype"`
    Payload any    `json:"payload"`
}

任何类型的值都可以分配给该字段并进行编组:

v := WsPayload{
    Message: "msg",
    Etype:   "report",
    Payload: EventReport{Title: "title"},
}
b, err := json.Marshal(v)
if err != nil { /* handle error */ }
// b is {"action":"","message":"msg","etype":"report","payload":{"title":"title","body":"","date":"","time":"","type":"","id":"","photo":null}}

要解组 JSON,请使用 json.RawMessage 作为变体字段:

var v WsPayload
u := struct {
    *WsPayload
    Payload json.RawMessage `json:"payload"`
}{
    &v,
    nil,
}
if err := json.Unmarshal(b, &u); err != nil { 
    /* handle error */ 
}

打开 Etype 字段以解组变体部分:

switch u.Etype {
case "report":
    var r EventReport
    if err := json.Unmarshal(u.Payload, &r); err != nil {
        log.Fatal(err)
    }
    v.Payload = r
// handle other types here...
default:
    log.Fatalf("type %s not handled", u.Etype)
}

输出是可变的

v

https://go.dev/play/p/bDAQnZFWDvw

© www.soinside.com 2019 - 2024. All rights reserved.