第9章 構造体

構造体の基本

Go言語における構造体(Structs)は、関連するデータを一つの単位でまとめるためのデータ型です。構造体は、異なる型のデータをフィールドとして持つことができます。以下に「構造体の基本」についての具体的な事例を示します。


構造体の定義

構造体はstructキーワードを用いて定義されます。構造体はフィールド(属性)の集まりで、各フィールドには名前と型があります。

package main

import "fmt"

// Person 構造体の定義
type Person struct {
    Name string
    Age  int
}


構造体のインスタンス化

構造体は、変数としてインスタンス化することができます。構造体リテラルを使用して、フィールドに値を割り当てます。

func main() {
    // Person 構造体のインスタンスを作成
    p := Person{Name: "Alice", Age: 30}

    // 構造体のフィールドにアクセス
    fmt.Println(p.Name) // 出力: Alice
    fmt.Println(p.Age)  // 出力: 30
}


フィールドへのアクセスと変更

構造体のフィールドには、ドット演算子.を使用してアクセスし、値を読み取ったり変更したりできます。

p.Age = 31
fmt.Println(p.Age) // 出力: 31


構造体のポインタ

構造体のポインタを使用すると、構造体のインスタンスを直接変更することができます。Goでは、構造体のポインタを通じてフィールドにアクセスする際に、ポインタの逆参照を明示的に行う必要はありません。

pPointer := &p
pPointer.Age = 32
fmt.Println(p.Age) // 出力: 32

※ポインタについてはポインタの記事を参考にしてください


構造体の応用

Go言語における構造体の応用は、その基本的な使用法を超えて、より複雑なデータ構造の作成や、関数との組み合わせ、インターフェースの実装などを含みます。以下に構造体の応用についての具体的な事例を示します。Go言語における構造体の応用は、その基本的な使用法を超えて、より複雑なデータ構造の作成や、関数との組み合わせ、インターフェースの実装などを含みます。以下に構造体の応用についての具体的な事例を示します。


構造体にメソッドを関連付ける

Go言語では、構造体に関連付けられたメソッド(関数)を定義できます。これにより、オブジェクト指向プログラミングのようなパターンを実現できます。

type Rectangle struct {
    Width, Height float64
}

// Rectangle構造体に関連付けられたAreaメソッド
func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

func main() {
    rect := Rectangle{Width: 10, Height: 5}
    fmt.Println("面積:", rect.Area()) // 出力: 面積: 50
}


構造体の埋め込み(組み込み)

他の構造体を埋め込むことにより、継承のような機能を模倣できます。これは「合成(Composition)」とも呼ばれます。

type Person struct {
    Name string
    Age  int
}

type Employee struct {
    Person  // Person構造体の埋め込み
    ID      int
}

func main() {
    emp := Employee{
        Person: Person{Name: "Alice", Age: 28},
        ID:     1234,
    }

    fmt.Println("従業員:", emp.Name, "年齢:", emp.Age, "ID:", emp.ID)
    // 出力: 従業員: Alice 年齢: 28 ID: 1234
}


構造体とインターフェース

構造体はインターフェースを実装することができます。これにより、ポリモーフィズムのようなパターンを実現できます。

type Shape interface {
    Area() float64
}

type Circle struct {
    Radius float64
}

func (c Circle) Area() float64 {
    return math.Pi * c.Radius * c.Radius
}

func main() {
    var s Shape = Circle{Radius: 5}
    fmt.Println("面積:", s.Area()) // 出力: 面積: 78.53981633974483
}


構造体とデータ管理

Go言語では、構造体を使用してデータを効率的に管理し、整理することができます。構造体は、異なる型のデータを一つの単位としてグループ化するのに適しています。以下に「構造体とデータ管理」に関する具体的な事例を示します。


JSONデータのエンコードとデコード

Go言語のencoding/jsonパッケージを使用すると、構造体とJSONデータ間で相互変換を行うことができます。

package main

import (
    "encoding/json"
    "fmt"
    "log"
)

type Product struct {
    ID    int    `json:"id"`
    Name  string `json:"name"`
    Price float64 `json:"price"`
}

func main() {
	// エンコード
    p := Product{ID: 1, Name: "Gopher", Price: 9.99}
    jsonData, err := json.Marshal(p)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(string(jsonData)) // 出力: {"id":1,"name":"Gopher","price":9.99}

    // デコード
    jsonData := []byte(`{"id":1,"name":"Gopher","price":9.99}`)
    var p Product
    err := json.Unmarshal(jsonData, &p)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("%+v\n", p) // 出力: {ID:1 Name:Gopher Price:9.99}
}


構造体のスライスとマップ

構造体を使用して、スライスやマップ内のデータを整理し、複雑なデータ構造を作成することができます。

// 構造体のスライス
var products []Product
products = append(products, Product{ID: 2, Name: "Gopher plush", Price: 19.99})
fmt.Println(products) // 出力: [{2 Gopher plush 19.99}]

// 構造体を含むマップ
productMap := make(map[int]Product)
productMap[p.ID] = p
fmt.Println(productMap) // 出力: map[1:{1 Gopher 9.99}]


練習問題1.

Carという名前の構造体を定義し、Make(文字列型)、Model(文字列型)、Year(整数型)の3つのフィールドを持たせてください。その後、この構造体のインスタンスを作成し、各フィールドに任意の値を設定して、それらの値を出力してください。

package main

import "fmt"

// ここに Car 構造体を定義

func main() {
    // ここに Car のインスタンスを作成し、フィールドを設定して出力するコードを記述
}


練習問題2.

Rectangle構造体を定義し、WidthHeightという名前の2つのフィールド(ともに整数型)を持たせなさい。この構造体にAreaという名前のメソッドを追加し、長方形の面積(幅×高さ)を返すようにしてください。Rectangleのインスタンスを作成し、Areaメソッドを呼び出してその結果を出力してください。

package main

import "fmt"

// ここに Rectangle 構造体と Area メソッドを定義

func main() {
    // ここに Rectangle のインスタンスを作成し、Area メソッドを呼び出して出力するコードを記述
}


練習問題3.

PersonEmployeeという2つの構造体を定義しなさい。Person構造体にはNameAgeというフィールドを、Employee構造体にはPerson構造体を埋め込み、さらにIDというフィールドを追加してください。Employeeのインスタンスを作成し、それぞれのフィールドに値を設定して出力してください。

package main

import "fmt"

// ここに Person と Employee 構造体を定義

func main() {
    // ここに Employee のインスタンスを作成し、フィールドを設定して出力するコードを記述
}