go-functional-options について
Go のコンストラクターや公開 API を設定する関数型オプションパターンを解説する開発スキルです。採用時期や実装構成、設定構造体との使い分けを検討できます。
主な機能
- 01関数型オプションを選ぶ基準
- 02Option インターフェースと内部構造体
- 03With* コンストラクターの指針
- 04設定構造体との比較
- 05テストとドキュメントの考慮点
活用シーン
- 01コンストラクターのオプション引数の設定
- 02オプション追加を見込む API の設計
- 03オプションと設定構造体の選択
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ cxuu/ golang-skills --skill go-functional-optionsインストール後、Claude Code で/go-functional-optionsを入力して読み込まれたか確認します。
同梱ファイルreferences/OPTIONS-VS-STRUCTS.md
詳細
関数型オプションパターン
関数型オプションは、内部の構造体に情報を記録する、不透明な Option 型を宣言するパターンです。コンストラクターはこれらのオプションを可変個受け取り、適用して結果を設定します。
リソースルーティング
references/OPTIONS-VS-STRUCTS.md- 設定用の構造体と関数型オプションのどちらを使うか選ぶ場合、インターフェースベースのオプションパターンを完全に実装する場合、またはハイブリッドなコンストラクター API を評価する場合に参照してください。
使用する場面
次の場合に関数型オプションを使用します。
- コンストラクターや公開 API に3 個以上のオプション引数がある
- 今後新しいオプションが増える可能性がある拡張可能な API
- 呼び出し側の使いやすさが重要である(デフォルト値を渡す必要がない)
パターン
主な構成要素
- 非公開の
options構造体 - すべての設定を保持します - 公開された
Optionインターフェース - 非公開のapplyメソッドを持ちます - オプション型 - インターフェースを実装します
With*コンストラクター - オプションを作成します
Option インターフェース
type Option interface {
apply(*options)
}
非公開の apply メソッドにより、このパッケージのオプションだけを使用できます。
比較:関数型オプションと設定用構造体
| 項目 | 関数型オプション | 設定用構造体 |
|---|---|---|
| 拡張性 | 新しい With* 関数を追加 | 新しいフィールドを追加(互換性を損なう可能性があります) |
| デフォルト値 | コンストラクターに組み込み | ゼロ値、または個別にデフォルト値を設定 |
| 呼び出し側の使いやすさ | 異なる値だけを指定 | 構造体全体を作成する必要があります |
| テスト容易性 | オプションを比較可能 | 構造体を比較 |
| 複雑さ | 定型コードが増える | 設定がよりシンプル |
設定用構造体を優先する場合:オプションが 3 個未満、オプションがほとんど変更されない、通常すべてのオプションをまとめて指定する、または内部 API のみの場合。
クロージャーを使わない理由
クロージャーのみのオプションよりもインターフェース方式が推奨される理由は、次のとおりです。
- テスト容易性 - テストやモックでオプションを比較できます
- デバッグのしやすさ - オプションに
fmt.Stringerを実装できます - 柔軟性 - オプションに追加のインターフェースを実装できます
- 可視性 - オプション型がドキュメントに表示されます
クイックリファレンス
// 1. Unexported options struct with defaults
type options struct {
field1 Type1
field2 Type2
}
// 2. Exported Option interface, unexported method
type Option interface {
apply(*options)
}
// 3. Option type + apply + With* constructor
type field1Option Type1
func (o field1Option) apply(opts *options) { opts.field1 = Type1(o) }
func WithField1(v Type1) Option { return field1Option(v) }
// 4. Constructor applies options over defaults
func New(required string, opts ...Option) (*Thing, error) {
o := options{field1: defaultField1, field2: defaultField2}
for _, opt := range opts {
opt.apply(&o)
}
// ...
}
チェックリスト
-
options構造体が非公開である -
Optionインターフェースが非公開のapplyメソッドを持つ - 各オプションに
With*コンストラクターがある - オプションを適用する前にデフォルト値を設定する
- 必須パラメーターを
...Optionと分ける
関連スキル
- インターフェース設計:
Optionインターフェースの設計や、インターフェース方式とクロージャー方式の選択については、go-interfaces を参照してください - 命名規則:
With*コンストラクター、オプション型、非公開の options 構造体の命名については、go-naming を参照してください - 関数設計:ファイル内でのコンストラクターの整理や、可変長引数を持つシグネチャーの書式については、go-functions を参照してください
- ドキュメント:
Option型、With*関数、コンストラクターの動作の文書化については、go-documentation を参照してください
外部リソース
- 自己参照関数とオプションの設計 - Rob Pike
- 使いやすい API のための関数型オプション - Dave Cheney
コメント
Markdown 対応