BioErrorLog Tech Blog

試行錯誤の記録

Go言語のFunctional Options Patternを理解する

Go言語におけるFunctional Options Patternを簡単に整理します。

はじめに

あるGo製ライブラリを使っていたところ、Functional Options Patternに遭遇しました。

Go言語におけるFunctional Options Patternとは何か、メモします。

The English translation of this post is here.

Go言語でFunctional Options Pattern

Functional Options Patternを最小限に実装した簡単な例がこちら:

type Coffee struct {
    Sugar int  // Sugar specifies the number of sugar spoons
    Milk  bool // Milk indicates whether milk is added or not
}

type Option func(*Coffee)

func NewCoffee(opts ...Option) *Coffee {
    c := &Coffee{
        Sugar: 0,
        Milk:  false,
    }

    for _, opt := range opts {
        opt(c)
    }

    return c
}


func WithSugar(spoons int) Option {
    return func(c *Coffee) {
        c.Sugar = spoons
    }
}

func WithMilk() Option {
    return func(c *Coffee) {
        c.Milk = true
    }
}

このNewCoffee()を呼び出す例:

func main() {
    c1 := NewCoffee()
    c2 := NewCoffee(WithSugar(2))
    c3 := NewCoffee(WithMilk(), WithSugar(1))
}

このようにしてNewCoffeeに可変長のオプション引数を定義できます。

NewCoffee内でデフォルト値Coffee{Sugar: 0, Milk: false}を設定した上で、Option型の関数が引数に渡された場合はその関数を介してフィールドを上書きします。

おわりに

Go言語のFunctional Options Patternを最小限の例でまとめました。

より詳細な解説や歴史的背景については、下記の記事がおすすめです:

Functional options for friendly APIs | Dave Cheney

以上、どなたかの参考になれば幸いです。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

参考