柔軟なAPIの構築
このパターンを適用します
「柔軟なAPIの構築」はCoddyKit上の無料Go Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはGo Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Go Academyコースには全4レッスンが含まれています。
パターンを適用する
ここでパターン全体を組み立てます。必須の引数に加えて、Optionの可変長リストを受け取るコンストラクターを作ります。
可変長コンストラクター
必須パラメーターを先に置き、その後に...OptionとしてOptionを続けます。
package main
import "fmt"
type Server struct {
Host string
Port int
}
type Option func(*Server)
func WithPort(p int) Option { return func(s *Server) { s.Port = p } }
func NewServer(host string, opts ...Option) *Server {
s := &Server{Host: host}
for _, opt := range opts {
opt(s)
}
return s
}
func main() {
s := NewServer("localhost", WithPort(8080))
fmt.Printf("%+v\n", *s)
}Optionなしで呼び出す
Optionは可変長なので、呼び出し側は完全に省略して、コンストラクターが設定する値に任せることもできます。
package main
import "fmt"
type Server struct{ Host string; Port int }
type Option func(*Server)
func NewServer(host string, opts ...Option) *Server {
s := &Server{Host: host}
for _, o := range opts { o(s) }
return s
}
func main() {
s := NewServer("localhost")
fmt.Printf("%+v\n", *s)
}複数のOptionを指定して呼び出す
必要な数だけOptionを並べられます。呼び出し箇所でも、それぞれの意図が明確に読み取れます。
package main
import "fmt"
type Server struct {
Host string
Port int
Timeout int
TLS bool
}
type Option func(*Server)
func WithPort(p int) Option { return func(s *Server) { s.Port = p } }
func WithTimeout(t int) Option { return func(s *Server) { s.Timeout = t } }
func WithTLS() Option { return func(s *Server) { s.TLS = true } }
func NewServer(host string, opts ...Option) *Server {
s := &Server{Host: host}
for _, o := range opts { o(s) }
return s
}
func main() {
s := NewServer("localhost", WithPort(9000), WithTimeout(60), WithTLS())
fmt.Printf("%+v\n", *s)
}呼び出しから意図が分かる
NewServer("localhost", WithPort(9000), WithTLS())を位置引数による呼び出しと比較してみましょう。シグネチャを確認しなくても、意図が明らかです。
後からOptionを追加する
新しい設定が必要になったら、WithX関数を追加します。既存の呼び出し箇所は一切変更せず、そのままコンパイルできます。これが真の後方互換性です。
package main
import "fmt"
type Server struct{ Host string; Retries int }
type Option func(*Server)
func WithRetries(n int) Option { return func(s *Server) { s.Retries = n } }
func NewServer(host string, opts ...Option) *Server {
s := &Server{Host: host}
for _, o := range opts { o(s) }
return s
}
func main() {
fmt.Printf("%+v\n", *NewServer("h", WithRetries(5)))
}Optionを受け渡す
Optionは値なので、別の場所でスライスを構築し、それをコンストラクターに渡せます。
package main
import "fmt"
type Server struct{ Host string; Port int }
type Option func(*Server)
func WithPort(p int) Option { return func(s *Server) { s.Port = p } }
func NewServer(host string, opts ...Option) *Server {
s := &Server{Host: host}
for _, o := range opts { o(s) }
return s
}
func main() {
common := []Option{WithPort(443)}
s := NewServer("api", common...)
fmt.Printf("%+v\n", *s)
}公開APIとしてのOption
Option型とWithX関数をエクスポートすれば、ライブラリの利用者は内部実装に触れずに型を設定できます。
フィールドを非公開に保つ
Configのフィールドは非公開のままにできます。設定を行う正式な方法をOptionだけに限定できるため、不変条件を守れます。
このパターンが特に有効な場面
- オプションが多いライブラリのコンストラクター
- 成長しても安定性を保つ必要があるAPI
- クライアント、サーバー、ロガー、ビルダー
標準ライブラリにも見られるパターン
Goエコシステム全体でこのスタイルを目にします(gRPCや多くのドライバーなど)。このパターンを認識できると、それらのAPIにも親しみやすくなります。
クイックチェック
柔軟なAPIに関する知識を確認しましょう。
まとめ
Functional Optionsを使って柔軟なAPIを構築しました。
- 必須引数を先に置き、その後に
...Optionを続ける - Optionをループして1つずつ適用する
- 呼び出し側は0個でも複数でも指定でき、意図も明確になる
- 呼び出し側を壊さずに後からOptionを追加できる
よくある質問
「柔軟なAPIの構築」レッスンは無料ですか?
はい。「柔軟なAPIの構築」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Go Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Go Academyコースには全4レッスンが含まれています。
「柔軟なAPIの構築」で何を学びますか?
このパターンを適用します ブラウザで直接実行するハンズオンコードでGo Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Go Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのGo Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「柔軟なAPIの構築」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このGo Academyレッスンでコードを書いて実行できますか?
はい。すべてのGo Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- パラメータが多い場合の問題
- オプション関数
- 柔軟なAPIの構築
- デフォルト値とバリデーション