GoのFunctional Optionsの覚書
The Go Playgroundで試せます。
play.golang.org
Go言語でStructのインスタンスを生成するときに
New()
のような関数をよく作ることが多いと思います。その際に、オプションを指定するために
type Options struct {
Number int
}
func New(option *Option) {
}
みたいなのを定義してすることがあると思います。
この場合Optionに何も指定せずインスタンスを生成するときには
New(nil)
や
New(Option{})
などとして生成する必要があります。
個人的にあんまり綺麗じゃないと思っているのでこういうときにはFunctional Option Pattern
を使うようにしています。
要はなにもOptionがないときは
New()
で済むようにしたいという話です。
Hoge構造体のインスタンスを生成するときには
type Hoge struct {
Options Options
}
type Options struct {
// Number must be in this range (0~100)
Number int64
}
type SetOptionFunc func(*Options) error
func Number(number int64) SetOptionFunc {
return func(o *Options) error {
if number < 0 || 0 > 100 {
return errors.New("number must be in range (0~100)")
}
o.Number = number
return nil
}
}
func New(setOptionFuncs ...SetOptionFunc) *Hoge {
var options Options
for _, f := range setOptionFuncs {
f(&options)
}
return &Hoge{Options: options}
}
こんな感じにします。
New()
で設定したいOptionを受け取って設定する関数の配列を受け取るようにして設定するようにして、以下のように扱えるようにします。
func main() {
New()
New(Number(100))
}
また、このパターンは引数が多い関数を扱いやすくするのに使えます。
func Hoge(a int, b int, c int ..........) {}
みたく設定項目が多い関数だと大変だったり、oだと関数の引数にデフォルト値が指定できないとかいう煩わしさを解消できます。