Go言語のstructで構造体を定義する方法をわかりやすく解説

スポンサーリンク
スポンサーリンク

structの概要

構造体の定義と利用 Goの予約語

struct

概要structは、複数のフィールドを持つカスタムデータ型を定義するための構造体です。

  • 複数の異なる型のフィールドをまとめて管理できる。
  • メソッドを定義することで、オブジェクト指向的な振る舞いを実装できる。
  • ポインタを使って構造体を効率的に扱うことができる。

基本的なstructの使い方

以下のコードは、structを使って人物の情報を管理する例です。

package main

import "fmt"

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

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

    // フィールドにアクセス
    fmt.Println("名前:", p.Name)
    fmt.Println("年齢:", p.Age)
}

解説:

  • Personという構造体を定義し、Name(文字列)とAge(整数)のフィールドを持たせます。
  • p := Person{Name: "太郎", Age: 25}のようにフィールドを指定してインスタンスを作成します。
  • p.Namep.Age を使ってフィールドの値にアクセスできます。

実行結果:

名前: 太郎
年齢: 25

ポインタを使った構造体の参照

構造体は値型ですが、ポインタを使うと参照渡しが可能になります。

package main

import "fmt"

type Person struct {
    Name string
    Age  int
}

func changeAge(p *Person, newAge int) {
    p.Age = newAge // ポインタを介してフィールドを更新
}

func main() {
    p := Person{Name: "花子", Age: 30}

    fmt.Println("変更前の年齢:", p.Age)

    changeAge(&p, 35) // ポインタを渡す
    fmt.Println("変更後の年齢:", p.Age)
}

解説:

  • *Person型のポインタを受け取る関数changeAgeを定義します。
  • 関数内でp.Age = newAgeとすることで、元の構造体の値を直接変更できます。
  • &pを渡すことで、ポインタ経由で構造体を操作します。

実行結果:

変更前の年齢: 30
変更後の年齢: 35

構造体にメソッドを定義

Goでは、構造体にメソッドを定義することができます。

package main

import "fmt"

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

// メソッドの定義(ポインタレシーバ)
func (p *Person) Greet() {
    fmt.Printf("こんにちは、私は%sです。%d歳です。\n", p.Name, p.Age)
}

func main() {
    p := Person{Name: "次郎", Age: 20}
    p.Greet() // メソッドを呼び出し
}

解説:

  • func (p *Person) Greet()のように、structに関連するメソッドを定義できます。
  • ポインタレシーバ(*Person)を使うことで、オブジェクトのフィールドを変更するメソッドを作成できます。

実行結果:

こんにちは、私は次郎です。20歳です。

構造体の埋め込み(Goの疑似的な継承)

Goには継承はありませんが、構造体の埋め込みを使って親子関係のような構造を作ることができます。

package main

import "fmt"

// 基本構造体
type Person struct {
    Name string
    Age  int
}

// Personを埋め込む新しい構造体
type Employee struct {
    Person // 埋め込み
    Position string
}

func main() {
    e := Employee{
        Person:   Person{Name: "太郎", Age: 40},
        Position: "エンジニア",
    }

    fmt.Println("名前:", e.Name)       // Personのフィールドにもアクセスできる
    fmt.Println("年齢:", e.Age)
    fmt.Println("職業:", e.Position)
}

解説:

  • Employee構造体にPersonを埋め込むことで、Personのフィールドに直接アクセスできます。
  • e.Namee.Age のように、埋め込んだ構造体のフィールドを簡単に利用できます。

実行結果:

名前: 太郎
年齢: 40
職業: エンジニア

注意事項

  • 構造体は値型: そのまま代入するとコピーが作成されるため、変更を反映する場合はポインタを使う。
  • フィールド名は大文字でエクスポート: 他のパッケージからアクセスするには、フィールド名を大文字で始める必要がある。
  • 埋め込みは継承ではない: 埋め込みを使うと、フィールドやメソッドを持つことができるが、明示的な親子関係はない。

よくある質問

Q: 構造体のフィールドを後から追加できますか?
A: いいえ。Goの構造体は固定サイズのため、動的にフィールドを追加することはできません。
Q: 構造体のデフォルト値は?
A: 数値は0、文字列は""、ブーリアンはfalse、ポインタはnilになります。
Q: メソッドでポインタレシーバを使う理由は?
A: フィールドを変更する場合はポインタレシーバが必要です。値レシーバの場合、コピーが渡されるため変更が反映されません。
Q: Goにはクラスはないのですか?
A: はい。Goはオブジェクト指向言語ではなく、クラスの代わりにstructを使用します。

まとめ

  • structを使うと、複数のフィールドを持つカスタムデータ型を作成できる。
  • ポインタを使うと、構造体のフィールドを直接変更できる。
  • メソッドを定義することで、構造体に動作を追加できる。
  • 埋め込みを使うと、他の構造体を拡張することができる。