構造体のネスト
CoddyのGOジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 16/107。
ネストされた構造体とは、フィールドの1つとして別の名前付き構造体を含む構造体のことです。これにより、小さく再利用可能な型を組み合わせることで、複雑で階層的なデータをモデル化できます。
type Address struct {
Street string
City string
ZIP string
}
type Person struct {
Name string
Age int
Address Address // ネストされた構造体
}ネストされた構造体のフィールドにアクセスするには、フィールド名をドットで繋ぎます。
p := Person{
Name: "Alice",
Age: 30,
Address: Address{
Street: "123 Main St",
City: "Boston",
ZIP: "02101",
},
}
fmt.Println(p.Address.City) // Bostonネスト(入れ子)はコードの再利用を促進します。Address型は、フィールドを重複させることなく、Person、Company、Orderなどの複数の構造体で使用できます。このアプローチは、エンティティが他のエンティティを含むという現実世界の概念を反映しています。
type Company struct {
Name string
Employees int
Address Address // 同じ Address 型を再利用
}構造体は複数レベルの深さまでネストできますが、階層を浅く保つことで可読性が向上します。ネストされた構造体は、Goでオブジェクト指向のデータモデルを構築するための基本です。
チャレンジ
簡単現実世界の階層構造をモデル化する際に、ネストされた構造体(nested structs)がどのように役立つかを示す従業員管理システムを構築しましょう。従業員が部署に所属し、部署が場所情報を持つという構造を作成します。
コードを2つのファイルに分けて整理します:
models.go: 連携して動作する3つの構造体を定義します:Building(string) とFloor(int) フィールドを持つLocationName(string) とネストされたLocationフィールドを持つDepartmentID(int)、Name(string)、およびネストされたDepartmentフィールドを持つEmployee
main.go: 入力から従業員情報を読み取り、適切にネストされた構造体を持つ Employee を作成し、ネストされた構造を通じてフィールドにアクセスして完全な従業員プロファイルを表示します。
以下の入力が提供されます:
- 1行目: 従業員ID(整数)
- 2行目: 従業員名
- 3行目: 部署名
- 4行目: 建物名
- 5行目: 階数(整数)
出力形式:
Employee: [Name] (ID: [ID])
Department: [DepartmentName]
Location: [Building], Floor [Floor]例えば、101、Alice Chen、Engineering、Tower A、5 が与えられた場合、出力は以下のようになります:
Employee: Alice Chen (ID: 101)
Department: Engineering
Location: Tower A, Floor 5ドット記法を使用して構造体の階層を連鎖させ、ネストされたフィールドにアクセスします(例:employee.Department.Location.Building)。
チートシート
入れ子になった構造体(nested struct)とは、フィールドの1つとして別の名前付き構造体を含む構造体のことで、より小さく再利用可能な型を組み合わせることで階層的なデータをモデル化できます。
入れ子になった構造体の定義
type Address struct {
Street string
City string
ZIP string
}
type Person struct {
Name string
Age int
Address Address // 入れ子になった構造体
}入れ子になったフィールドへのアクセス
ドット記法を使用して、構造体の階層を辿ります:
p := Person{
Name: "Alice",
Age: 30,
Address: Address{
Street: "123 Main St",
City: "Boston",
ZIP: "02101",
},
}
fmt.Println(p.Address.City) // Boston入れ子になった構造体の再利用
同じ入れ子になった構造体型を、複数の親構造体で再利用できます:
type Company struct {
Name string
Employees int
Address Address // 同じAddress型を再利用
}入れ子になった構造体はコードの再利用を促進し、エンティティが他のエンティティを含むという現実世界の概念を反映します。構造体は何段階にも深く入れ子にすることができますが、階層を浅く保つことで可読性が向上します。
自分で試してみよう
package main
import "fmt"
func main() {
// 従業員情報を読み込む
var id int
var name string
var deptName string
var building string
var floor int
fmt.Scanln(&id)
fmt.Scanln(&name)
fmt.Scanln(&deptName)
fmt.Scanln(&building)
fmt.Scanln(&floor)
// TODO: 適切にネストされた構造体を使用してEmployeeを作成する
// models.goのLocation、Department、Employee構造体を使用する
// 入力値ですべてのネストされたフィールドを初期化する
// TODO: 次の形式で従業員プロファイルを出力する:
// Employee: [Name] (ID: [ID])
// Department: [DepartmentName]
// Location: [Building], Floor [Floor]
// ドット記法を使用してネストされたフィールドにアクセスする (例: employee.Department.Location.Building)
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
1Go オブジェクト指向の基礎
外部ファイルGo ワークスペースとモジュールパッケージとインポート公開された名前と非公開の名前Go におけるオブジェクト指向入門クラスとしての構造体構造体へのメソッド定義ポインタレシーバと値レシーバ構造体の初期化コンストラクタ関数まとめ:簡易計算機8エラー処理とOOP
error インターフェースカスタムエラー型エラーラッピング (fmt.Errorf)センチネルエラーerrors.Is() と errors.As()Panic、Defer、Recover復習 - ファイルパーサー