可选参数传递小技巧(option)
问题2
场景:假设你写的一个sdk在用户使用时,希望传入一些可选的参数,那么哪种传参写法更优雅呢?
现在假设你需要写一个发送消息的方法,这个方法包含一些可选参数,参数类型如下:
// 发送消息
type Options struct {
FromUser string
ToUser string
Content string
Type string
}
常见做法
这个时候,这个个option如何传入创建连接的方法就有点小技巧了,常见的做法有以下几种:
创建一个构造函数,不想要的参数就传一个空参。
这种写法比较鸡肋,你需要严格按照参数列表和类型进行传参,虽然为空是缺省,但也不友好。func Send(fromUser string, touser string, Content string, Type string) { if fromUser == "" { } if touser == "" { } if Content == "" { } if Type == "" { } // do something }
- 根据常见的可选组合创建多个options的构造函数。然后提供WithXXX的方法。
这种写法还不错,可以选择性的传参,但是传参之前需要构造一个option,然后对option进行一些操作,其实也是有点麻烦的。
package main
import "fmt"
// 发送消息
type MessageParams struct {
FromUser string
ToUser string
Content string
Type string
}
func NewMessageParams(fromUser, toUser string) *MessageParams {
mp := &MessageParams{}
mp.FromUser = fromUser
mp.ToUser = toUser
mp.Content = "单图"
mp.Type = "img"
//do something
return mp
}
func (mp *MessageParams) WithContent(content string) {
if content != "" {
mp.Content = content
}
}
func (mp *MessageParams) WithType(msgType string) {
if msgType != "" {
mp.Type = msgType
}
}
func SendMessage(mp *MessageParams) {
fmt.Printf("fromUser [%v] => toUser [%s] :type[%v] => content [%v]\n",
mp.FromUser,
mp.ToUser,
mp.Type,
mp.Content)
// do something
}
func main() {
mp := NewMessageParams("A", "B")
mp.WithType("img")
mp.WithContent("发送了一条单图消息")
SendMessage(mp)
}
优雅做法
可以通过golang可选参数的形式,传入Option结构体(结构体中包含一个返回options指针的函数),动态的对参数进行构造。
这种写法在一些sdk中很常见。
package main
import "fmt"
// 发送消息
type MessageParams struct {
FromUser string
ToUser string
Content string
Type string
}
type Option struct {
f func(*MessageParams)
}
func WithContent(content string) Option {
return Option{func(mp *MessageParams) {
mp.Content = content
}}
}
func WithType(msgType string) Option {
return Option{func(mp *MessageParams) {
mp.Type = msgType
}}
}
func WithFromUser(fromUser string) Option {
return Option{func(mp *MessageParams) {
mp.FromUser = fromUser
}}
}
func WithToUser(toUser string) Option {
return Option{func(mp *MessageParams) {
mp.ToUser = toUser
}}
}
func SendMessage(ops ...Option) {
mp := &MessageParams{}
for _, do := range ops {
do.f(mp)
}
fmt.Printf("fromUser [%v] => toUser [%s] :type[%v] => content [%v]\n",
mp.FromUser,
mp.ToUser,
mp.Type,
mp.Content)
// do something
}
func main() {
SendMessage(
WithFromUser("A"),
WithToUser("B"),
WithContent("发送图片"),
WithType("img"))
}
参考链接:
golang option可选传参小技巧
本作品采用《CC 协议》,转载必须注明作者和本文链接