在Golang中创建可选输入有效载荷

guicsvcw  于 2023-09-28  发布在  Go
关注(0)|答案(3)|浏览(127)

我一直在为EL平台构建SDK。创建事件时,有多个有效载荷要输入。但是有三个有效载荷是强制性的,其他的是可选的。所以问题是我不知道如何让它成为可选项。

func (e *Events) Create(title, eventType, subType string, skills []string, prerequisite, description, about, subTitle string, preference map[string]bool) (string, error) {
    url := "https://api-dev.einstonlabs.com/api/v1/events"
    headers := map[string]string{
        "Content-Type":  "application/json",
        "Authorization": "Bearer " + e.instance.Token,
    }

    payload := map[string]interface{}{
        "title":   title,
        "type":    eventType,
        "subType": subType,
    }

    if skills != nil {
        payload["skills"] = skills
    }
    if prerequisite != "" {
        payload["prerequisite"] = prerequisite
    }
    if description != "" {
        payload["description"] = description
    }
    if about != "" {
        payload["about"] = about
    }
    if subTitle != "" {
        payload["subTitle"] = subTitle
    }
    if preference != nil {
        payload["preference"] = preference
    }

    jsonPayload, err := json.Marshal(payload)
    if err != nil {
        return "", fmt.Errorf("error encoding JSON payload: %v", err)
    }

    resp, err := http.Post(url, headers["Content-Type"], bytes.NewReader(jsonPayload))
    if err != nil {
        return "", fmt.Errorf("error creating event: %v", err)
    }
    defer resp.Body.Close()

    var response map[string]interface{}
    if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {
        return "", fmt.Errorf("error parsing response JSON: %v", err)
    }

    if status, ok := response["status"].(bool); ok && status {
        data := response["data"].(map[string]interface{})
        return data["id"].(string), nil
    }

    message, _ := response["message"].(string)
    return "", fmt.Errorf("event creation failed: %s", message)
}

我在下面分享代码。参数中只有title、eventType和subType是必填的,其他参数是可选的

iszxjhcz

iszxjhcz1#

我的习惯是,当有3个以上的参数时,最好创建一个结构来携带参数。

type CreateArgs struct {
    Title, EventType, SubType                  string
    Skills                                     []string
    Prerequisite, Description, About, SubTitle string
    Preference                                 map[string]bool
}

func (e *Events) Create(args CreateArgs) (string, error) {

}

对于您当前的代码,也许这样更容易

type Payload map[string]any

func (e *Events) Create(p Payload) (string, error) {
    // todo check the required filed
    if _,ok := p["title"];!ok{
        return "",fmt.Errorf("title is required")
    }
}
wnvonmuf

wnvonmuf2#

与其将payload作为一个map,不如引入一个带有json:..标签的响应结构体,这样就可以利用encoding/json库的全部功能将其封送为json字符串。可选字段应该用omitempty标记,这样封送器就不会在输出中包含它们。
Docs
“omitempty”选项指定如果字段具有空值(定义为false、0、nil指针、nil接口值以及任何空数组、切片、Map或字符串),则应从编码中省略该字段。作为特殊情况,如果字段标记为“-”,则始终省略该字段。请注意,名称为“-”的字段仍然可以使用标记“-,”生成。
结构体应该是这样的

type Payload struct {
    Title     string `json:"title"`
    EventType string `json:"type"`
    SubType   string `json:"subType"`

    // next fields will be skipped if their value is empty
    // (e.g. empty string, 0, false, nil etc.)
    OptionalString string `json:"optional_string,omitempty"`
    OptionalInt    int    `json:"optional_int,omitempty"`
}

确保导出所有字段(大写),以便库可以读取它们。
同样的考虑也适用于response。严格类型结构体而不是map[string]interface{}将消除所有类型Assert。

rt4zxlrg

rt4zxlrg3#

您可以在这里使用选项模式。在这种模式下,

  • 函数的强制参数像往常一样出现在其签名中,
  • 其可选参数与类型func(o *options)的可变列表通信。这些由接收函数用来将选项结构体设置为所需的状态。

本文Functional Options in Go: Implementing the Options Pattern in Golang by Soham Kamani描述了该模式,下面是a small example。我还在Apache的Gremlin驱动程序中发现了这种模式的一个示例,它用于配置数据库连接。

package main

import "fmt"

type (
    options struct {
        message string
    }
    update func(*options)
)

var defaults = options{"Hello, 世界"}

func greet(prefix string, updates ...update) {
    o := defaults
    for _, u := range updates {
        u(&o)
    }

    fmt.Println(prefix, o.message)
}

func main() {
    greet("defaults: ")
    greet("options: ", func(o *options) { o.message = "Hello, World" })

    // Output:
    // defaults:  Hello, 世界
    // options:  Hello, World
}

相关问题