見出し画像

golang 構造体/structの使い方と注意点について

今回は構造体/structの使い方と注意点ついて紹介していきます。


構造体/struct

構造体/structは、異なるデータ型の複数の変数を一つの単位でまとめるためのデータ構造です。
まとめられた各変数はこの構造体のメンバー/フィールドと呼ばれます。
構造体はプログラミングにおいてデータのモデリングや、関連するデータを意味のある単位としてグループ化するのに使用されます。


構造体の使い方

構造体の定義

構造体は以下のように定義します。

type Person struct {
    Name string
    Age  int
}

Personという名前の構造体を定義しており、NameとAgeという二つのフィールドを持っているという状態です。


構造体のインスタンス化

定義した構造体の型から実際のオブジェクトを生成するために構造体のインスタンス化を行う必要があります。
Go言語では構造体を用いることで、オブジェクト指向におけるクラスのインスタンス化の役割を担います。

構造体のインスタンスを作成するには、いくつかの方法があります。


ゼロ値で初期化

構造体の新しいインスタンスを作成し、すべてのフィールドをその型のゼロ値で初期化することができます。

var p Person

上記コードの場合は、Personは構造体の型で、pはその型の新しいインスタンスということになります。


フィールドを指定して初期化

構造体のインスタンスを作成し、フィールドに対して値を設定します。

p := Person{Name: "Alice", Age: 30}

上記コードの場合は、PersonのNameとAgeフィールドを指定して初期化しています。


new()関数を使って初期化

new()関数を使って構造体の新しいインスタンスを作成し、そのポインタを返します。

p := new(Person)

上記コードの場合は、pは*Person型(Personのポインタ)となり、すべてのフィールドはゼロ値で初期化されます。


リテラルを使って初期化

構造体リテラルを使用して、構造体のインスタンスを直接初期化することもできます。

p := Person{"Bob", 25}

上記コードの場合は、フィールドの値は順番に指定されています。


構造体のメソッド

構造体にメソッドを定義することで、オブジェクト指向プログラミングのようなパターンを実現することができます。

メソッドは特定の構造体のインスタンス(レシーバ)に対して操作を行います。

type Person struct {
    Name string
    Age  int
}

func (p Person) Greet() string {
    return "Hello, my name is " + p.Name
}

上記コードの場合は、Person型の各インスタンスにGreetメソッドが追加され、その人物の挨拶文を返しています。

構造体のインスタンスがあれば、そのインスタンスに対してメソッドを呼び出すことができます。

p := Person{Name: "Alice", Age: 30}
greeting := p.Greet()
fmt.Println(greeting) 

構造体の状態を変更するためには、ポインタレシーバを使用するメソッドを定義します。

func (p *Person) SetAge(newAge int) {
    p.Age = newAge
}

p := Person{Name: "Alice", Age: 30}
p.SetAge(31)
fmt.Println(p.Age)

このように書くことでメソッド内の変更が呼び出し元のインスタンスに反映されます。


構造体の注意点

Go言語の開発において構造体は避けては通れないほどによく使われます。よく使う分、注意しておかなければいけない点も抑えておく必要があります。


エクスポート

構造体のフィールド名が大文字で始まる場合、そのフィールドはパッケージ外からアクセス可能になります。
一方で小文字で始まるフィールドはパッケージ内からのみアクセス可能です

type Person struct {
    Name string // 外部からアクセス可能
    age  int    // 外部からアクセス不可能
}


ポインタ

構造体を関数に渡すとき、その値のコピーが作成されます。
そのため、構造体の状態を変更したい場合は、ポインタを渡す必要があります。

func (p Person) Greet() string {
    return "Hello, my name is " + p.Name
}

func (p *Person) SetAge(newAge int) {
    p.age = newAge
}

メソッドを定義する際にも、ポインタレシーバを使用するか値レシーバを使用するかを選ぶ必要があります。


構造体タグ

構造体タグを使用することで、JSONのシリアライズ/デシリアライズ時のフィールド名や他の形式でのデータ表現を制御することができます。

type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}


構造体の比較

構造体内に比較不可能なフィールド(スライスやマップなど)が含まれている場合、構造体全体をすることができません。

type Point struct {
    X, Y int
}

p1 := Point{1, 2}
p2 := Point{1, 2}
if p1 == p2 {
    fmt.Println("p1 と p2 は等しい")
}


golangをもっと詳しくなりたい方に

初めてのGo言語

Go言語の入門から応用まではこの一冊で網羅されています。説明も順序立てて説明されており完成度の高い参考書となっています。


詳解Go言語Webアプリケーション開発

こちらはGo言語の基礎知識を得たあとに読むことをすすめる本となっています。ハンズオン形式で手を動かしながら実装をしていくことができるため、実際の開発を意識しながらGo言語を学ぶことができます。

以下の記事では他にも筆者が実際に読んでおすすめしたい本をまとめています。


【Go入門】Golang基礎入門 + 各種ライブラリ + 簡単なTodoWebアプリケーション開発(Go言語)

まだGo言語の勉強を始めていない方、全くの初心者の方にはこちらのUdemy教材が最もおすすめです。

この教材ではgolangの基礎について網羅的に学ぶことができます。ただ見て学ぶだけでなく、講座の中でアプリ作成まで行うことで学んだことの理解をさらに深めることができます。


現役シリコンバレーエンジニアが教えるGo入門 + 応用でビットコインのシストレFintechアプリの開発

個人的に最も勉強になったのは「現役シリコンバレーエンジニアが教えるGo入門 + 応用でビットコインのシストレFintechアプリの開発」という教材です。
本格的なレクチャーに入る前に、なぜGoなのか、なぜFintechなのかについて説明されていることで、Goの概念や意味について大枠から理解することができます。

以下の記事では筆者が実際に受講したおすすめUdemy教材をまとめています。

※本ページではアフィリエイトリンク(PR)が含まれています


この記事が参加している募集

この経験に学べ

この記事が気に入ったらサポートをしてみませんか?