3
0

More than 3 years have passed since last update.

golang functional option

Last updated at Posted at 2019-11-23

Optionalな引数、どうしてますか?

pythonやjavascriptであれば

def hoge(a, b="bbb", c=123):
   pass

こんな風にすれば、関数はoptionalな引数を持つことができますが、Golangではこういう文法はありません。
調べると「Functional Optionを使いましょう」という記述に沢山出会います。

実際にFunctional Optionってどうやればいいんだろう?ということでやってみました。

実装

クラスのコンストラクタの場合

struct Sample {
   a string
   b string
   c int
}
func (s *Sample) init(){
   // init Sample
}
func NewSample(a string, b string, c int) *Sample {
   s := &Sample{a,b,c}
   s.init()
   return s
}

たとえばこんなコードがあるとします。

b,c をFunctional Optionにするとこんな感じになります。

type Sample struct {
   a string
   b string
   c int
}
func (s *Sample) init(){
   // init Sample
}
func NewSample(a string, options ...Option) *Sample {
   s := &Sample{a, defaultB, defaultC}
   for _, f := range options {
      f(s)
   }
   s.init()
   return s
}
type Option func(s *Sample)

func WithB(b string) Option {
   return func(s *Sample){
      s.b = b
   }
}
func WithC(c int) Option {
   return func(s *Sample){
      s.c = c
   }
}

実行

func main(){
   s := NewSample("aaa", WithB("bbb"), WithC(123))
}

こんな風にすれば、nilのような不要なパラメータが出現する事もなく、type safeなgolangの特徴を崩す事もなくoptionを導入できそうです。

関数の場合

関数では、クラスのように状態を持つことができるstructが存在しないため、新たに導入する必要がありそうです。

func hoge(a string, b string, c int){
   // do something with a,b,c
}

上記関数に対して、b,cをFunctional Optionにしてみます。

func hoge(a string, options ...Option){
   o := &option{defaultB, defaultC}
   for _, f := range options {
      f(o)
   }
   // do something with a, o.b, o.c
}
type option struct {
   b string
   c int
}
type Option func(o *option)

func WithB(b string) Option {
   return func(o *option){
      o.b = b
   }
}
func WithC(c int) Option {
   return func(o *option){
      o.c = c
   }
}

実行

func main(){
   hoge("aaa", WithB("bbb"), WithC(123))
}

こんな風にoption structを導入することで、クラスのコンストラクタと同様な手順で関数のオプションをFunctional Option化することができそうです。
optionというstructが導入されましたが、無駄な設定がなくtype safeなgolangの特徴を壊していないかと思います。

感想

最近仕事でgolangを書き始めました。
独特なルールを持つ言語なので、golangの特徴を生かした書き方をいろいろ探してみたいと思っています。

参考

https://commandcenter.blogspot.com/2014/01/self-referential-functions-and-design.html
https://medium.com/@dreissenzahn/functional-options-in-go-35279f535c6

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0