最近在看gin的配置,然后发现配置方式很独特,通过了解原来是一种函数选项模式实现的,今天就顺便给自己做个笔记
函数选项式(Functional Options) 是一种模式,在该模式中,你可以声明一个不透明的 Option 类型,该类型在某些内部结构体中记录信息。你接受这些可变数量的选项,并根据内部结构上的选项记录的完整信息进行操作。
将此模式用于构造函数和其他公共 API 中的可选参数,你预计这些参数需要扩展,尤其是在这些函数上已经有三个或更多参数的情况下。适合多个可选参数,初始化结构体来用,
既保持了兼容性,而且每增加1个新属性只需要1个With函数即可,大大减少了修改代码的风险
type DbServer struct {
User string
Password string
Port int
Host string
Charset string
MaxOpenConns int
}
//初始化一个Service
func NewDbServer(user string, password string, port int, host string) *DbServer {
return &DbServer{user, password, name, port, host}
}
但是有个问题,因为golang支持函数重载,加入我们DbServer结构体中的其他属性也需要设置为非必填,该怎么处理
比如:除了user, password, port, host为必选字段外,charset是可选,如果增加其他可选,又需要再次增加函数
func NewDbServerWithCharset(user string, password string, port int, host string, charset string) *DbServer {
return &DbServer{user, password, port, host, charset}
}
缺点: 1.创建太多的NewDbServer函数,增加开发量 2.代码冗余 3.无扩展性,如果再增加Server他属性呢
整个模式的实现分为三部分:
我们分别用栗子讲讲各步骤的具体实现
type Option func(*DbServer)
func WithCharset(charset string) Option {
return func(s *DbServer) {
s.Charset = charset
}
}
func WithMaxOpenConns(maxOpenConns int) Option {
return func(s *DbServer) {
s.MaxOpenConns = maxOpenConns
}
}
NewDbServer中的可选参数opts,类型是Option,也就是WithCharset, 或者WithMaxOpenConns。然后对参数进行遍历进行,执行option函数去对DbServer对应的属性进行修改
func NewDbServer(user string, password string, name string, port int, host string, opts ...Option) *Server {
//创建DbServer对象,并填写可选项的默认值
server := &DbServer{
User: user
Password: password
Port: port
Host: host
}
//都选项列表中每项都应用
for _, option := range opts {
option(server)
}
return s
}
使用的话就是
svr := NewDbServer(
"username",
"password",
3306,
"xxx",
WithCharset("UTF-8"),
WithMaxOpenConns(100),
)
其实你会发现基本上框架的初始化都是使用了这种模式,比如go-micro
想必大家看完后也基本上了解了个大概了,但是这种方式最好的适用场景还是多参数配置上,而且是那种可选参数配置,如果我们只有两三个参数,且无后续扩展的话就没必要这么用了,反而会让我们程序显得更复杂不容易懂,好了今天的分享就到这里了
【记录分享点滴】
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。