Go语言能否扩展结构体并适配原有函数?以go-gitlab为例
问题:扩展go-gitlab的SetSlackServiceOptions结构体并传入SetSlackService函数可行吗?
在使用go-gitlab SDK时,我需要扩展gitlab包内的SetSlackServiceOptions结构体,在自有包中为其新增字段,同时希望将自定义的新结构体传入该包的SetSlackService函数以扩展HTTP请求,请问该需求是否可实现?
相关代码如下:
gitlab包中的SetSlackServiceOptions结构体:
package gitlab // SetSlackServiceOptions struct type SetSlackServiceOptions struct { WebHook *string `url:"webhook,omitempty" json:"webhook,omitempty" ` Username *string `url:"username,omitempty" json:"username,omitempty" ` Channel *string `url:"channel,omitempty" json:"channel,omitempty"` }
gitlab包中的SetSlackService函数:
package gitlab func (s *ServicesService) SetSlackService(pid interface{}, opt *SetSlackServiceOptions, options ...OptionFunc) (*Response, error) { project, err := parseID(pid) if err != nil { return nil, err } u := fmt.Sprintf("projects/%s/services/slack", url.QueryEscape(project)) req, err := s.client.NewRequest("PUT", u, opt, options) if err != nil { return nil, err } return s.client.Do(req, nil) }
回答
直接把自定义结构体传入原包的SetSlackService函数是不行的——毕竟Go是强类型语言,你的自定义结构体和gitlab包的SetSlackServiceOptions是完全不同的类型,参数类型不匹配会直接编译报错。不过我们可以用Go的结构体嵌入技巧,封装一个自己的函数来实现需求,完美达成扩展HTTP请求的目标。
步骤1:定义带扩展字段的自定义结构体
在你的自有包中,通过嵌入gitlab的SetSlackServiceOptions结构体,快速复用原有字段,再添加你需要的自定义字段:
package mypackage import "github.com/xanzy/go-gitlab" // 自定义结构体,嵌入原gitlab结构体 type CustomSetSlackOptions struct { *gitlab.SetSlackServiceOptions // 嵌入后可直接使用原结构体的所有字段 CustomField *string `url:"custom_field,omitempty" json:"custom_field,omitempty"` AnotherField *int `url:"another_field,omitempty" json:"another_field,omitempty"` }
步骤2:封装自己的SetSlackService函数
原包的SetSlackService逻辑其实很清晰:解析项目ID、构建请求URL、创建并发送请求。我们可以完全复用这个逻辑,只是把参数换成自己的自定义结构体,这样请求序列化时就会包含原字段和你的新字段:
package mypackage import ( "fmt" "net/url" "github.com/xanzy/go-gitlab" ) func CustomSetSlackService(s *gitlab.ServicesService, pid interface{}, opt *CustomSetSlackOptions, options ...gitlab.OptionFunc) (*gitlab.Response, error) { // 复用原包的项目ID解析逻辑 project, err := gitlab.ParseID(pid) if err != nil { return nil, err } // 构建和原函数一致的请求URL u := fmt.Sprintf("projects/%s/services/slack", url.QueryEscape(project)) // 传入自定义结构体创建请求,序列化时会包含所有字段 req, err := s.Client.NewRequest("PUT", u, opt, options) if err != nil { return nil, err } // 发送请求 return s.Client.Do(req, nil) }
使用方式
现在你可以像调用原函数一样,使用自己封装的函数,传入带扩展字段的结构体:
// 初始化gitlab客户端 client, _ := gitlab.NewClient("your-token") // 构建自定义参数 webhook := "https://your-slack-webhook.com" customField := "my-custom-value" opt := &mypackage.CustomSetSlackOptions{ SetSlackServiceOptions: &gitlab.SetSlackServiceOptions{ WebHook: &webhook, }, CustomField: &customField, } // 调用自定义函数 resp, err := mypackage.CustomSetSlackService(client.Services, "your-project-id", opt)
这种方式既保留了原SDK的功能,又完美实现了字段扩展和请求扩展的需求,完全符合你的预期。
内容的提问来源于stack exchange,提问作者JAttanonRadar
相关产品推荐
相关产品推荐

