0Pricing
Go Academy · レッスン

柔軟な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フィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. パラメータが多い場合の問題
  2. オプション関数
  3. 柔軟なAPIの構築
  4. デフォルト値とバリデーション
← Go Academyに戻る