0Pricing
Go Academy · レッスン

コンストラクターパターン

Goらしいコンストラクターの構築

「コンストラクターパターン」はCoddyKit上の無料Go Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはGo Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Go Academyコースには全4レッスンが含まれています。

コンストラクタが必要な理由

Goには型用のnewキーワードも、クラスコンストラクタもありません。入力を検証し、初期化済みの値またはポインタを返すNew...という名前の関数を使うのが慣例です。

シンプルなNew関数

呼び出し側が共有インスタンスを扱えるように、ポインタを返します。

package main
import "fmt"

type Server struct {
    Host string
    Port int
}

func NewServer(host string, port int) *Server {
    return &Server{Host: host, Port: port}
}

func main() {
    s := NewServer("localhost", 8080)
    fmt.Println(s.Host, s.Port)
}

コンストラクタでの検証

コンストラクタは、入力を検証してエラーを返すのに適した場所です。

package main
import ("errors"; "fmt")

type Config struct{ Workers int }

func NewConfig(workers int) (*Config, error) {
    if workers < 1 {
        return nil, errors.New("workers must be >= 1")
    }
    return &Config{Workers: workers}, nil
}

func main() {
    c, err := NewConfig(4)
    fmt.Println(c, err)
}

Functional Optionsパターン

Functional Optionsパターンを使用すると、APIを壊さずにオプションの設定を追加できます。

package main
import "fmt"

type Server struct{ host string; port int; timeout int }
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 NewServer(host string, opts ...Option) *Server {
    s := &Server{host: host, port: 8080, timeout: 30}
    for _, o := range opts { o(s) }
    return s
}

func main() {
    s := NewServer("localhost", WithPort(9090), WithTimeout(60))
    fmt.Println(s.port, s.timeout)
}

ビルダーパターン

複雑なオブジェクトには、ビルダーパターンを使ってセッターメソッドをチェーンし、結果を返します。

package main
import "fmt"

type QueryBuilder struct{ table, where string; limit int }

func (q *QueryBuilder) Table(t string) *QueryBuilder { q.table = t; return q }
func (q *QueryBuilder) Where(w string) *QueryBuilder { q.where = w; return q }
func (q *QueryBuilder) Limit(n int)   *QueryBuilder { q.limit = n; return q }
func (q *QueryBuilder) Build() string {
    return fmt.Sprintf("SELECT * FROM %s WHERE %s LIMIT %d", q.table, q.where, q.limit)
}

func main() {
    sql := (&QueryBuilder{}).Table("users").Where("age>18").Limit(10).Build()
    fmt.Println(sql)
}

値とポインタの返し分け

構造体が小さく不変なら値を返し、大きい、可変、またはインターフェースを実装している場合はポインタを返します。

  • 小さな設定用構造体 → 値
  • 状態を持つオブジェクト(サーバー、クライアント、プール) → ポインタ
  • ポインタレシーバでインターフェースを実装している場合 → ポインタ

デフォルト値パターン

オプションを適用する前に、defaults関数または構造体リテラルを使用して適切なデフォルト値を設定します。

package main
import "fmt"

type Cache struct{ maxSize int; ttlSecs int }

func defaultCache() Cache { return Cache{maxSize: 100, ttlSecs: 300} }

func NewCache(opts ...func(*Cache)) *Cache {
    c := defaultCache()
    for _, o := range opts { o(&c) }
    return &c
}

func main() {
    c := NewCache(func(c *Cache) { c.maxSize = 500 })
    fmt.Println(c.maxSize, c.ttlSecs) // 500 300
}

Singletonパターン

sync.Onceを使用すると、共有リソースを正確に1回だけ初期化できます。

package main
import ("fmt"; "sync")

type DB struct{ DSN string }

var (
    instance *DB
    once     sync.Once
)

func GetDB(dsn string) *DB {
    once.Do(func() { instance = &DB{DSN: dsn} })
    return instance
}

func main() {
    db1 := GetDB("postgres://...")
    db2 := GetDB("ignored")
    fmt.Println(db1 == db2) // true
}

コンストラクタのテスト

エラーを返すコンストラクタは、簡単にテストできます。

package main
import ("errors"; "fmt")

type Pool struct{ size int }

func NewPool(size int) (*Pool, error) {
    if size <= 0 { return nil, errors.New("size must be positive") }
    return &Pool{size: size}, nil
}

func main() {
    _, err := NewPool(-1)
    fmt.Println(err) // size must be positive
    p, _ := NewPool(5)
    fmt.Println(p.size) // 5
}

init()を避ける

init()関数は自動的に実行されるため、テストが困難です。init()で暗黙的に初期化するよりも、エラーを返す明示的なコンストラクタを使用してください。

簡単な確認

Functional Optionsパターンによって何を実現できますか。

まとめ: コンストラクタパターン

要点:

  • コンストラクタとしてNew...関数を使用します
  • 検証に失敗した場合はエラーを返します
  • 柔軟なオプション設定にはFunctional Optionsを使用します
  • 複雑なクエリや設定用オブジェクトにはビルダーパターンを使用します
  • init()よりも明示的なコンストラクタを優先します

練習問題

Functional Optionsを使用するNewHTTPClientコンストラクタを実装してください。WithTimeout、WithBaseURL、WithMaxRetriesオプションに対応してください。

よくある質問

「コンストラクターパターン」レッスンは無料ですか?

はい。「コンストラクターパターン」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Go Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Go Academyコースには全4レッスンが含まれています。

「コンストラクターパターン」で何を学びますか?

Goらしいコンストラクターの構築 ブラウザで直接実行するハンズオンコードでGo Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Go Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのGo Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「コンストラクターパターン」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このGo Academyレッスンでコードを書いて実行できますか?

はい。すべてのGo Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

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

  1. 構造体の定義と利用
  2. 構造体のメソッド
  3. コンストラクターパターン
  4. 匿名構造体とコンポジション
← Go Academyに戻る