関数オプションパターン
関数オプションパターン(Functional Option Pattern)は、構造体の初期化時に必要なフィールドだけを指定できるようにする手法です。この方法では、個々のフィールドを設定する関数をオプション関数として定義し、コンストラクタにそれらのオプション関数を渡すことで、必要なフィールドのみを設定できます。
Go言語ではコンストラクタにオプション引数を実装する方法として、主に以下のパターンが挙げられます。
この記事ではそれぞれのパターンについて、簡単な実装例とメリット・デメリットを説明します。
関数オプションパターン(Functional Option Pattern)は、構造体の初期化時に必要なフィールドだけを指定できるようにする手法です。この方法では、個々のフィールドを設定する関数をオプション関数として定義し、コンストラクタにそれらのオプション関数を渡すことで、必要なフィールドのみを設定できます。
type User struct {
name string
email string
age int
isActive bool
}
type Option func(*User)
func WithName(name string) Option {
return func(u *User) {
u.name = name
}
}
func WithEmail(email string) Option {
return func(u *User) {
u.email = email
}
}
func WithAge(age int) Option {
return func(u *User) {
u.age = age
}
}
func WithActive(active bool) Option {
return func(u *User) {
u.isActive = active
}
}
func NewUser(opts ...Option) *User {
user := &User{}
for _, opt := range opts {
opt(user)
}
return user
}
ビルダーパターン(Builder Pattern)は、ステップバイステップで構造体を構築する手法です。この手法では、構造体のフィールドを設定するための一時的なビルダー構造体を作成し、最終的にターゲットの構造体を生成します。
type User struct {
name string
email string
age int
isActive bool
}
type UserBuilder struct {
user User
}
func NewUserBuilder() *UserBuilder {
return &UserBuilder{}
}
func (b *UserBuilder) WithName(name string) *UserBuilder {
b.user.name = name
return b
}
func (b *UserBuilder) WithEmail(email string) *UserBuilder {
b.user.email = email
return b
}
func (b *UserBuilder) WithAge(age int) *UserBuilder {
b.user.age = age
return b
}
func (b *UserBuilder) WithActive(active bool) *UserBuilder {
b.user.isActive = active
return b
}
func (b *UserBuilder) Build() User {
return b.user
}
可変長引数パターン(Variadic Functions Pattern)は、コンストラクタに可変長引数を渡すことで、オプション引数を実装する手法です。この手法では、デフォルト値を持つフィールドについては明示的に指定しなくても良くなります。
type User struct {
name string
email string
age int
isActive bool
}
func NewUser(name, email string, opts ...option) *User {
user := User{
name: name,
email: email,
age: 0,
}
for _, opt := range opts {
opt(&user)
}
return &user
}
type option func(*User)
func WithAge(age int) option {
return func(u *User) {
u.age = age
}
}
func WithActive(active bool) option {
return func(u *User) {
u.isActive = active
}
}
Go言語のコンストラクタにオプション引数を実装する代表的な方法として、関数オプションパターン、ビルダーパターン、可変長引数パターンがあります。
関数オプションパターンは柔軟性と可読性のバランスが良く、テストも容易であるため、よく使われるパターンです。ビルダーパターンは可読性が高い反面、コード量が多くなる傾向にあります。可変長引数パターンは簡潔ですが、オプション関数が増えると可読性が低下する点に注意が必要です。
これらのパターンを適切に使い分けることで、Go言語のコードベースの保守性と拡張性を高めることができます。構造体のフィールドの数やプロジェクトの要件に応じて、最適なパターンを選択することをおすすめします。
1996年生まれ。中部大学大学院にてコンピュータビジョン関連の深層学習の研究に注力したのち、2021年4月に株式会社medibaに入社。 KDDIグループ企業各社のDeveloperが集い、エンジニアが楽しめるイベントを提供するコミュニティ「KGDC」のイベント運営も行っています。
記事に関する質問は、フッター掲載の各種SNSにてお問い合わせください。