繁体   English   中英

我可以使用结构向接口添加字段吗?

[英]Can I add a field to an interface using a struct?

我遇到了一个有趣的场景。 我有一个结构,我想向它添加一个字段消息。 我可以通过Can I add a field to an existing struct with Go? .

type User struct {
 // user fields here
}

type UpdationResponse struct {
 User
 Message string `json:"message,omitempty"` 
}

func SendSuccessResponse(w http.ResponseWriter, r *http.Request, resp interface{}) interface{} {
    w.Header().Set("Content-Type", "application/json")
    return json.NewEncoder(w).Encode(resp)
}

这将返回 JSON 之类的

{
    "id": "50",
    "firstName": "vibhor",
    "lastName": "agrawal",
    "email": "someemail@emailprovider.com",
    "isVerified": false,
    "joinedAt": "2020-06-28T09:45:59Z",
    "fullName": "vibhor agrawal"
    "message": "Profile Updated."
}

因此,这有助于我发送用户数据以及一条消息,比如“配置文件已更新。”。 如果我想对我所有的 API 进行概括。 有什么我可以做的。

我试过了:

type SuccessResponse struct {
 Data    interface{}
 Message string `json:"message,omitempty"`
}

func SendSuccessResponse(w http.ResponseWriter, r *http.Request, resp SuccessResponse) interface{} {
    w.Header().Set("Content-Type", "application/json")
    return json.NewEncoder(w).Encode(resp)
}

但是当我将它作为 JSON 发送时,它的结构类似于

{
    "Data": {
        "id": "50",
        "firstName": "vibhor",
        "lastName": "agrawal",
        "email": "someemail@emailprovider.com",
        "isVerified": false,
        "joinedAt": "2020-06-28T09:45:59Z",
        "fullName": "vibhor agrawal"
    },
    "message": "Profile Updated."
}

有没有一种方法可以在数据本身中添加消息并将其概括为我所有的成功响应而不管Data

简而言之:这是不可能的。

长答案:

在您的第一个示例中, struct UpdationResponse扩展了 struct User 这也称为混合。 简单地说UpdationResponse获取User的所有属性并自己使用它们。

在您的第二个示例中,结构SuccessResponse定义了可以是任何内容的属性Data DataSuccessResponse的子元素,因此会被编组。 没有办法绕过它,因为 go 源代码是静态类型的并提前编译。

您可以让响应实现json.Marshaler接口,让它分别编组这两个字段,然后在最后合并结果。

func (r Response) MarshalJSON() ([]byte, error) {
    out1, err := json.Marshal(r.Data)
    if err != nil {
        return nil, err
    }

    type _Response Response // to avoid infinite recursion
    out2, err := json.Marshal((_Response)(r))
    if err != nil {
        return nil, err
    }

    // NOTE: this may need more work to handle other cases, for example
    // the Data field's dynamic type being a slice of some type, rather than
    // a single struct....
    if size := len(out1); size > 0 && out1[size-1] == '}' {
        if size > 2 {
            out1[size-1] = ',' // replace "}" with ","
        } else {
            out1 = out1[:size-1] // drop "}"
        }

        out2 = out2[1:]              // drop "{"
        out := append(out1, out2...) // merge
        return out, nil
    }

    return out2, nil
}

https://play.golang.org/p/9u0jcEgt2zL

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM