匿名構造体とコンポジション
埋め込みと構造体ベースのコード再利用
「匿名構造体とコンポジション」はCoddyKit上の無料Go Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはGo Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Go Academyコースには全4レッスンが含まれています。
匿名構造体
匿名構造体には名前付き型がありません。インラインで定義し、短期間だけ使うデータ、テーブル駆動テスト、一時的なグループ化に便利です。
package main
import "fmt"
func main() {
point := struct{ X, Y int }{X: 3, Y: 7}
fmt.Println(point.X, point.Y)
}テーブルテストでの匿名構造体
Goでは、テーブル駆動テストに匿名構造体のスライスを使用するのが一般的なイディオムです。
package main
import "fmt"
func double(n int) int { return n * 2 }
func main() {
tests := []struct{ input, want int }{
{1, 2}, {5, 10}, {0, 0},
}
for _, tt := range tests {
got := double(tt.input)
if got != tt.want {
fmt.Printf("FAIL: double(%d) = %d, want %d\n", tt.input, got, tt.want)
}
}
fmt.Println("all tests passed")
}構造体の埋め込み
型を構造体に埋め込むと、そのフィールドとメソッドが外側の構造体に昇格されます。
package main
import "fmt"
type Animal struct{ Name string }
func (a Animal) Speak() string { return a.Name + " speaks" }
type Dog struct {
Animal // embedded
Breed string
}
func main() {
d := Dog{Animal: Animal{"Rex"}, Breed: "Labrador"}
fmt.Println(d.Name) // promoted field
fmt.Println(d.Speak()) // promoted method
}複数の型の埋め込み
構造体には複数の型を埋め込めます。同じフィールド名やメソッド名が衝突する場合は、明示的に解決する必要があります。
package main
import "fmt"
type Logger struct{}
func (Logger) Log(s string) { fmt.Println("[LOG]", s) }
type Metrics struct{}
func (Metrics) Count() int { return 42 }
type Service struct {
Logger
Metrics
Name string
}
func main() {
svc := Service{Name: "auth"}
svc.Log("started") // from Logger
fmt.Println(svc.Count()) // from Metrics
}埋め込みと継承
Goにはクラス継承がありません。埋め込みはコンポジションです。
- 埋め込みによってフィールドとメソッドは昇格されますが、外側の型がサブタイプになるわけではありません
Animalが必要な場所にDogを渡すことはできません- ポリモーフィズムにはインターフェースを、コードの再利用には埋め込みを使用します
昇格されたメソッドのオーバーライド
外側の構造体で独自のメソッドを定義すると、埋め込まれたメソッドを隠すことができます。
package main
import "fmt"
type Base struct{}
func (Base) Hello() string { return "Base hello" }
type Child struct{ Base }
func (Child) Hello() string { return "Child hello" } // shadows Base.Hello
func main() {
c := Child{}
fmt.Println(c.Hello()) // Child hello
fmt.Println(c.Base.Hello()) // Base hello (explicit)
}設定用の匿名構造体
名前付き型を定義せずに関連する設定をまとめるには、匿名構造体を使用します。
package main
import "fmt"
func main() {
cfg := struct {
Host string
Port int
TLS bool
}{
Host: "api.example.com",
Port: 443,
TLS: true,
}
fmt.Println(cfg)
}インターフェースの埋め込み
構造体にインターフェースを埋め込むと、モックやデフォルト実装に便利です。
package main
import "fmt"
type Reader interface{ Read() string }
type Mock struct{ Reader } // embed interface
func main() {
m := Mock{}
fmt.Printf("%T\n", m.Reader) // <nil> — not set
// Assign a real impl at test time:
_ = m
}構造体コンポジションの注意点
次の点に注意してください。
- 2つの埋め込み型に同じフィールド名やメソッド名がある場合の、曖昧なセレクタ
- 埋め込まれたポインタがnilのため、メソッド呼び出し時にパニックが発生すること
- 埋め込みは継承ではないため、外側の型を埋め込まれた型の代わりに使用できないこと
匿名構造体の比較
フィールド名と型が同じ2つの匿名構造体は、タグも一致していれば互いに代入可能です。
package main
import "fmt"
func main() {
a := struct{ X, Y int }{1, 2}
b := struct{ X, Y int }{1, 2}
fmt.Println(a == b) // true
}簡単な確認
構造体に型を埋め込むと何が実現されますか。
まとめ: コンポジション
要点:
- 匿名構造体はテーブルテストや短期間だけ使うデータに適しています
- 埋め込みによってフィールドとメソッドが昇格されます。これは継承ではなくコンポジションです
- 外側の型では、埋め込まれたメソッドを隠すことができます
- 曖昧なセレクタは明示的に解決します
- ポリモーフィズムにはインターフェースを使用します
練習問題
Timestamp struct{ CreatedAt, UpdatedAt string }とData struct{ Key, Value string }を埋め込むTimestampedRecord構造体を作成してください。インスタンス化し、昇格されたすべてのフィールドを出力してください。
よくある質問
「匿名構造体とコンポジション」レッスンは無料ですか?
はい。「匿名構造体とコンポジション」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Go Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Go Academyコースには全4レッスンが含まれています。
「匿名構造体とコンポジション」で何を学びますか?
埋め込みと構造体ベースのコード再利用 ブラウザで直接実行するハンズオンコードでGo Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Go Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのGo Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「匿名構造体とコンポジション」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このGo Academyレッスンでコードを書いて実行できますか?
はい。すべてのGo Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- 構造体の定義と利用
- 構造体のメソッド
- コンストラクターパターン
- 匿名構造体とコンポジション