功能选项(functional option)

功能选项(functional option)

初始版本 #

  1. 定义option类型。
type option func(*Foo)

其中Foo为需要设置option的对象类型。option是用来设置选项的函数。

  1. 为Foo类型添加应用options列表的函数Option。
func (f *Foo) Option(opts ...option) {
    for _, opt := range opts {
        opt(f)
    }
}
  1. 提供设置特定选项(如verbosity)的函数。
func Verbosity(v int) option {
    return func(f *Foo) {
        f.verbosity = v
    }
}
  1. 客户端设置选项。
foo.Option(pkg.Verbosity(3))

让Option方法返回先前的值 #

用空接口来保存选项值的方案 #

type option func(*Foo) interface{}
func Verbosity(v int) option {
    return func(f *Foo) interface{} {
        previous := f.verbosity
        f.verbosity = v
        return previous
    }
}

func (f *Foo) Option(opts ...option) (previous interface{}) {
    for _, opt := range opts {
        previous = opt(f)
    }
    return previous
}

客户端使用方式如下:

prevVerbosity := foo.Option(pkg.Verbosity(3))
foo.DoSomeDebugging()
foo.Option(pkg.Verbosity(prevVerbosity.(int)))

返回option函数的设置方式 #

空接口显得比较笨重(clumsy),设置选项的返回值是另一个option函数,新返回的option函数在调用时会将值设置为原来的值。

type option(f *Foo) option

// Option sets the options specified.
// It returns an option to restore the last arg's previous value.
func (f *Foo) Option(opts ...option) (previous option) {
    for _, opt := range opts {
        previous = opt(f)
    }
    return previous
}

func Verbosity(v int) option {
    return func(f *Foo) option {
        previous := f.verbosity
        f.verbosity = v
        return Verbosity(previous)
    }
}

尤其要注意最后返回的是Verbosity(previous)。这里返回的是个undo closure。客户端使用方式如下:

prevVerbosity := foo.Option(pkg.Verbosity(3))
foo.DoSomeDebugging()
foo.Option(prevVerbosity)

或者用defer的用法:

func DoSomethingVerbosely(foo *Foo, verbosity int) {
    // Could combine the next two lines,
    // with some loss of readability.
    prev := foo.Option(pkg.Verbosity(verbosity))
    defer foo.Option(prev)
    // ... do some stuff with foo under high verbosity.
}

From #

Self-referential functions and the design of options