Go練習問題3-08:構造体の埋め込みを理解しよう

記事内に商品プロモーションを含む場合があります

Go言語の初心者向け問題3-08:構造体の埋め込みを理解しよう

この問題を解くために必要な知識:
レベル1~2の知識関数の定義と呼び出し関数の戻り値と複数の戻り値関数の可変長引数無名関数(匿名関数)クロージャ構造体の定義コンストラクタ関数構造体の埋め込みメソッドの定義とレシーバインターフェース型アサーション型スイッチ

<<前の問題 問題集Top 次の問題>>

Go言語の文法「構造体の埋め込み」とは





ここでは構造体の埋め込みの意味や使い方を復習します。必要ない方はここをクリックして練習問題へ飛びましょう。

Go言語では、構造体を他の構造体に埋め込むことで、コードの再利用性を高め、より簡潔で効率的なコードを書くことができます。

この「構造体の埋め込み」は、他のオブジェクト指向言語での「継承」に似ていますが、Go言語には独自の特徴があります。

構造体の埋め込みとは?

構造体の埋め込みは、ある構造体の中に別の構造体を「匿名フィールド」として含めることを指します。

このフィールドには名前がなく、埋め込まれた構造体のフィールドやメソッドは、直接アクセスできるようになります。

package main

import "fmt"

type Address struct {
    City, State string
}

type Person struct {
    Name string
    Age  int
    Address
}

func main() {
    p := Person{
        Name: "John Doe",
        Age:  30,
        Address: Address{
            City:  "New York",
            State: "NY",
        },
    }

    // Addressフィールドに直接アクセス可能
    fmt.Printf("%s lives in %s, %s.\n", p.Name, p.City, p.State)
}

上記のコードでは、Person構造体にAddress構造体が埋め込まれています。p.Cityp.Stateのように、Addressのフィールドに直接アクセスできる点が特徴です。

構造体の埋め込みのメリット

  • コードの再利用: 共通のフィールドやメソッドをまとめることで、DRY (Don’t Repeat Yourself) 原則に従った設計が可能です。
  • シンプルな構文: 埋め込み構造体のフィールドに直接アクセスできるため、冗長なコードを避けられます。

このように、Go言語の構造体の埋め込みは、設計の柔軟性を高める非常に強力な機能です。

基本的な使い方を理解し、自分のプロジェクトで積極的に活用していきましょう。 ​

Go練習問題3-8:構造体の埋め込みを使ったプログラムを作成しよう

「構造体の埋め込み」を利用して、人物の名前と住所を保持し、画面に出力するプログラムを作成してください。

Person構造体にAddress構造体を埋め込み、住所情報を直接アクセスできるようにします。

この問題の要件

以下の要件に従ってコードを完成させてください。

  • Address構造体を定義し、CityStateという2つのフィールドを持つこと。
  • Person構造体を定義し、NameAgeというフィールドを持つこと。また、Address構造体を匿名フィールドとして埋め込むこと。
  • Person構造体のインスタンスを作成し、Name, Age, City, Stateの各フィールドに適切な値を設定すること。
  • fmt.Printfを使用して、名前と住所情報を画面に出力すること。

ただし、以下のような実行結果となるコードを書くこと。

*****↓↓正解コードの実行結果の例↓↓*****

山田太郎さんは、東京都の東京に住んでいます。

この問題を解くヒント

1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。

ヒント1【コードの構成を見る】

正解のコードは上から順に以下のような構成となっています。

1.パッケージの宣言
2.fmtパッケージのインポート

3.Address構造体の定義
 3-1. Cityフィールドの定義
 3-2. Stateフィールドの定義

4.Person構造体の定義
 4-1. Nameフィールドの定義
 4-2. Ageフィールドの定義
 4-3. Address構造体の埋め込み

5.main関数
 5-1. Person構造体のインスタンス化
 5-2. フィールドへの値の割り当て
 5-3. fmt.Printfを使用した出力

ヒント2【穴埋め問題にする】

以下のコードをコピーし、コメントに従ってコードを完成させて下さい。

package main

import "fmt"

// Address構造体は、都市と州の情報を保持します
type Address struct {
    City, State string
}

// Person構造体は、名前と年齢を保持します。
// また、Address構造体を埋め込んでいます。
type Person struct {
    Name string
    Age  int
    Address  // 構造体の埋め込み。PersonはAddressのフィールドにも直接アクセスできます。
}

// main関数はプログラムのエントリーポイントです
func main() {
    // Person構造体のインスタンスを作成し、初期値を設定します
    p := Person{
        Name: "山田太郎",
        Age:  30,
        /*【穴埋め問題1】ここにAddress構造体のインスタンスを作成し、CityとStateフィールドに値を設定してください。*/
    }

    // 構造体の埋め込みにより、直接CityやStateにアクセスできます
    /*【穴埋め問題2】ここに構造体の埋め込みを利用して名前、都市、州を出力するコードを書いてください。*/
}

 

このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。

解答例と解説

この問題の一つの正解例とそのコードの解説を以下に示します。

正解コードの例

例えば以下のようなプログラムが考えられます。

package main

import "fmt"

// Address構造体は、都市と州の情報を保持します
type Address struct {
    City, State string
}

// Person構造体は、名前と年齢を保持します。
// また、Address構造体を埋め込んでいます。
type Person struct {
    Name string
    Age  int
    Address  // 構造体の埋め込み。PersonはAddressのフィールドにも直接アクセスできます。
}

// main関数はプログラムのエントリーポイントです
func main() {
    // Person構造体のインスタンスを作成し、初期値を設定します
    p := Person{
        Name: "山田太郎",
        Age:  30,
        Address: Address{
            City:  "東京",
            State: "東京都",
        },
    }

    // 構造体の埋め込みにより、直接CityやStateにアクセスできます
    fmt.Printf("%sさんは、%sの%sに住んでいます。\n", p.Name, p.State, p.City)
}

正解コードの解説

このプログラムでは、Go言語の「構造体の埋め込み」という技術を使用しています。

以下の説明を通じて、構造体の定義、埋め込み、およびそれらを使ったデータ操作について学びましょう。

パッケージの宣言とインポート

package main

import "fmt"

Go言語のすべてのプログラムはパッケージから始まります。package mainはエントリーポイントを定義するもので、main関数が含まれているパッケージとして機能します。

import "fmt"はフォーマット関連の関数(例:PrintlnPrintf)を提供するfmtパッケージをインポートしています。

Address構造体の定義

type Address struct {
    City, State string
}

ここではAddressという名前の構造体を定義しています。CityStateという2つの文字列フィールドを持つシンプルな構造体です。構造体は複数のフィールドをまとめて保持するために使用されます。

Person構造体の定義と構造体の埋め込み

type Person struct {
    Name string
    Age  int
    Address
}

Personという構造体を定義しています。この構造体はNameという文字列フィールドとAgeという整数フィールドを持ち、さらにAddress構造体を埋め込んでいます。

埋め込まれた構造体のフィールド(CityState)に直接アクセスできる点が特徴です。これにより、Person構造体がAddressのフィールドやメソッドも持つかのように扱うことができます。

main関数と構造体の操作

func main() {
    p := Person{
        Name: "山田太郎",
        Age:  30,
        Address: Address{
            City:  "東京",
            State: "東京都",
        },
    }
    fmt.Printf("%sさんは%sの%sに住んでいます。\n", p.Name, p.City, p.State)
}

main関数はプログラムのエントリーポイントです。この関数内でPerson構造体のインスタンスpを作成し、名前、年齢、都市、州の情報を設定しています。

Address構造体はPerson構造体内に埋め込まれているため、p.Cityp.Stateといった形式で直接アクセスが可能です。

このコードではfmt.Printfを使って、名前、都市、州の情報をフォーマットされた文字列として出力しています。

結論

このプログラムを通じて、Go言語の構造体の定義と埋め込みについて理解することができます。

構造体の埋め込みは、オブジェクト指向プログラミングにおける「継承」に似た機能を提供し、コードの再利用性を高め、シンプルで直感的なコードを記述するために非常に有効です。

今回の例では、人物情報を持つPerson構造体に、住所情報を持つAddress構造体を埋め込むことで、これらのデータを一つの構造体として扱えるようにしています。

<<前の問題 問題集Top 次の問題>>

この問題への質問・コメント

この問題を作成するにあたりAIを活用しています。

問題ないことは確認していますが、もし間違いや表現の違和感などありましたら、ご指摘頂けると大変助かります。






    Go練習問題集へ戻る
    トップページへ戻る