这种实现的优点是:输入的各种配置,可以选择不传入,不传入则使用默认配置;选择传入,则调用可视化的方法明确指定要设置的配置,比较优雅,而且不要求传入的顺序固定。缺点就是底层方法要多写一些代码,但是这样整体结构比较好看高级
以log初始化需要传入的配置为例
首先把所有需要配置的变量放在一个结构体里
type options struct {
path string
level string
isDebug bool
}
声明各个配置项的默认值
const (
defaultPath = "../log/default.log"
defaultLevel = "DEBUG"
defaultIsDebug = false
)
声明一个接口Option,内部有一个方法apply
再声明一个变量optionFunc ,实现这个接口,实现的方法很简单,实现apply方法即可
这里注意变量optionFunc是一个函数,他的apply方法内部逻辑就是把apply的参数当作自己的入参,具体做什么要看具体的optionFunc
type Option interface {
apply(*options)
}
type optionFunc func(*options)
// apply 的功能就是把o传给方法f,至于具体做什么,要看具体的方法,比如WithPath,就是修改o的属性path
func (f optionFunc) apply(o *options) {
f(o)
}
下面实现各个配置对应的方法,返回的都是接口类型,内部实际返回的是optionFunc类型的方法,方法内部的逻辑都不同,比如WithLevel 返回的方法就是修改传入的参数options的level变量
注意这个的options传的是指针,这样修改才能生效
func WithPath(path string) Option {
return optionFunc(func(o *options) {
o.path = path
})
}
func WithLevel(level string) Option {
return optionFunc(func(o *options) {
o.level = level
})
}
func WithIsDebug(isDebug bool) Option {
return optionFunc(func(o *options) {
o.isDebug = isDebug
})
}
使用场景
type Connection struct {
addr string
cache bool
timeout time.Duration
}
func NewConnect(addr string, opts ...Option) (*Connection, error) {
//首先创建默认配置
options := options{
timeout: defaultTimeout,
caching: defaultCaching,
}
for _, o := range opts {
o.apply(&options)
}
return &Connection{
addr: addr,
cache: options.caching,
timeout: options.timeout,
}, nil
}
func testConnect(){
NewConnect("localhost:1220",WithCaching(false),WithTimeout(3*time.Second))
}
这也是设计模式里面的选项模式