在Golang中实现事件接口的可选输入Payload方案咨询
优化Go SDK中Create事件的可选参数实现
你的现有代码已经实现了可选参数的核心逻辑(通过判断零值/nil决定是否加入payload),但最大的问题是调用Create时必须传入所有参数——哪怕不需要的可选参数,也得传空字符串、nil这类默认值,用起来很繁琐。下面给你两种更优雅的实现方式:
方式一:函数式选项模式(推荐)
这是Go生态里处理可选参数的标准优雅方案,调用方可以只传入需要的可选参数,代码可读性和扩展性都更强。
步骤1:定义选项结构体与选项函数
// EventOptions 存放创建事件的所有参数(必填+可选) type EventOptions struct { Title string EventType string SubType string Skills []string Prerequisite string Description string About string SubTitle string Preference map[string]bool } // EventOption 选项函数类型 type EventOption func(*EventOptions) // 定义各个可选参数的设置函数 func WithSkills(skills []string) EventOption { return func(o *EventOptions) { o.Skills = skills } } func WithPrerequisite(prerequisite string) EventOption { return func(o *EventOptions) { o.Prerequisite = prerequisite } } func WithDescription(description string) EventOption { return func(o *EventOptions) { o.Description = description } } func WithAbout(about string) EventOption { return func(o *EventOptions) { o.About = about } } func WithSubTitle(subTitle string) EventOption { return func(o *EventOptions) { o.SubTitle = subTitle } } func WithPreference(preference map[string]bool) EventOption { return func(o *EventOptions) { o.Preference = preference } }
步骤2:修改Create方法
func (e *Events) Create(title, eventType, subType string, opts ...EventOption) (string, error) { // 初始化选项,先填充必填参数 options := EventOptions{ Title: title, EventType: eventType, SubType: subType, } // 应用所有传入的可选选项 for _, opt := range opts { opt(&options) } 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": options.Title, "type": options.EventType, "subType": options.SubType, } // 可选参数判断逻辑和原代码一致 if options.Skills != nil { payload["skills"] = options.Skills } if options.Prerequisite != "" { payload["prerequisite"] = options.Prerequisite } if options.Description != "" { payload["description"] = options.Description } if options.About != "" { payload["about"] = options.About } if options.SubTitle != "" { payload["subTitle"] = options.SubTitle } if options.Preference != nil { payload["preference"] = options.Preference } // 后续JSON序列化、HTTP请求逻辑与原代码完全一致 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) }
调用示例
// 只传必填参数 eventID, err := events.Create("测试事件", "workshop", "technical") // 传必填+部分可选参数 eventID, err := events.Create( "测试事件", "workshop", "technical", WithSkills([]string{"Go", "API"}), WithDescription("这是一个Go SDK开发工作坊"), )
方式二:使用结构体封装参数
如果觉得函数式选项太繁琐,也可以直接用结构体封装所有参数,调用时只填充必填字段即可。
步骤1:定义参数结构体
type CreateEventParams struct { Title string // 必填 EventType string // 必填 SubType string // 必填 Skills []string // 可选 Prerequisite string // 可选 Description string // 可选 About string // 可选 SubTitle string // 可选 Preference map[string]bool // 可选 }
步骤2:修改Create方法
func (e *Events) Create(params CreateEventParams) (string, error) { // 先验证必填参数 if params.Title == "" || params.EventType == "" || params.SubType == "" { return "", fmt.Errorf("title, eventType and subType are required") } 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": params.Title, "type": params.EventType, "subType": params.SubType, } // 可选参数判断逻辑与原代码一致 if params.Skills != nil { payload["skills"] = params.Skills } if params.Prerequisite != "" { payload["prerequisite"] = params.Prerequisite } // 其余可选参数判断省略 // 后续请求逻辑与原代码一致 // ... }
调用示例
// 只传必填参数 eventID, err := events.Create(CreateEventParams{ Title: "测试事件", EventType: "workshop", SubType: "technical", }) // 传必填+部分可选参数 eventID, err := events.Create(CreateEventParams{ Title: "测试事件", EventType: "workshop", SubType: "technical", Skills: []string{"Go", "API"}, Description: "这是一个Go SDK开发工作坊", })
两种方式里,函数式选项模式更适合后续需要新增可选参数的场景(不用修改方法签名,扩展性更好);结构体方式更直观,适合参数相对固定的情况。
内容的提问来源于stack exchange,提问作者Shaheer
相关产品推荐
相关产品推荐

