golang 设计模式–函数式选项模式

  • 为 struct 结构体可能存在的字段设置默认值
  • struct 的成员可以改变

范例源码

https://github.com/micro/go-micro/blob/master/options.go

我们先定义一个 结构体Option 和对应的 OptionFunc 的函数类型

1
2
3
4
5
6
type Option struct {
    A string
    B string
    C int
}
type OptionFunc func(*Option)

然后利用闭包为每个字段编写一个设置值的 With 函数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
func WithA(a string) OptionFunc {
    return func(o *Option) {
        o.A = a
    }
}

func WithB(b string) OptionFunc {
    return func(o *Option) {
        o.B = b
    }
}

func WithC(c int) OptionFunc {
    return func(o *Option) {
        o.C = c
    }
}

然后,我们定义一个 默认的Option 函数 如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
var (
    defaultOption = setDefaultOption()
)

func setDefaultOption() *Option {
    return &Option{
        A: "A",
        B: "B",
        C: 100,
    }
}

最后编写,我们new 构造函数如下

1
2
3
4
5
6
7
8
func NewOption(opts ...OptionFunc) (opt *Option) {
    opt = defaultOption
    for _, o := range opts {
        o(opt)
    }
    defaultOption = setDefaultOption()
    return
}

这里需要注意,defaultOption = setDefaultOption() 一定别忘记。不然会相互影响

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
func TestNewOption(t *testing.T) {
    absOptions := newOptionABS("A", "B", 100)
    optionFast := NewOption()
    changeOption := NewOption(
        WithA("B"),
        WithB("A"),
    )
    // do
    t.Logf("absOptions %v", absOptions)
    t.Logf("optionFast %v", optionFast)
    t.Logf("changeOption %v", changeOption)
}

详细代码见