カテゴリ: Go言語 更新日: 2025/12/30

Go言語の構造体とポインタの関係!ポインタを使ったアクセス方法

Go言語の構造体とポインタの関係!ポインタを使ったアクセス方法
Go言語の構造体とポインタの関係!ポインタを使ったアクセス方法

先生と生徒の会話形式で理解しよう

生徒

「Go言語の構造体にポインタってどうやって使うんですか?」

先生

「構造体とポインタを組み合わせると、同じ変数を効率よく使い回すことができます。変更も共有されるので便利ですよ。」

生徒

「それってメモリとか関係してますか?」

先生

「はい、ポインタは“メモリの住所”のようなものです。詳しく説明していきましょう!」

1. ポインタとは?初心者向けにかんたん解説

1. ポインタとは?初心者向けにかんたん解説
1. ポインタとは?初心者向けにかんたん解説

ポインタ(pointer)とは、「変数が保存されている場所(メモリの番地)」を指し示す特別な変数です。ふつうの変数は数字や文字などの値そのものを入れていますが、ポインタはその値が置かれている場所を覚えています。

イメージで言うと、自分の家の場所を教える「住所」がポインタで、家の中にある家具などの中身が「値」です。住所だけ知っていれば、あとから家に行って中身を見たり並べ替えたりできますよね。同じように、ポインタがあれば変数の中身を直接変えることができます。

これがなぜ便利なのかというと、ポインタを使えば大きなデータを丸ごとコピーする必要がなくなり、プログラムが効率よく動くようになるからです。特に構造体のように複数の値をまとめて持つデータでは、ポインタがとても役に立ちます。

まずは、ポインタが「変数の場所を覚えているだけ」という点だけ理解できれば大丈夫です。下の短いサンプルを見ると、普通の変数とポインタ変数の違いが少しイメージしやすくなります。


num := 10
p := &num
fmt.Println(num) // 10
fmt.Println(*p)  // 10(ポインタを使って中身を取り出せる)

&numで変数numの場所を取得し、*pを使うとその場所の中身を読み取れます。「場所を覚える」と「場所の中身を見る」という二段階がポインタの基本です。

2. 構造体にポインタを使う理由とは?

2. 構造体にポインタを使う理由とは?
2. 構造体にポインタを使う理由とは?

構造体は、名前や年齢などいくつかの情報をまとめたものです。この構造体を関数に渡すとき、ポインタを使うと効率的に処理できます。

ポインタを使わずに渡すと、構造体のコピーが作られます。でもポインタを使えば、元のデータそのものを扱えるので、無駄なコピーが減って処理が速くなります

3. 構造体のポインタを作る基本文法

3. 構造体のポインタを作る基本文法
3. 構造体のポインタを作る基本文法

まずは構造体と、そのポインタを使ってみましょう。


type User struct {
    Name string
    Age  int
}

func main() {
    u := User{Name: "たろう", Age: 25}
    ptr := &u // ポインタを作成
    fmt.Println(ptr.Name) // ポインタ経由でも「.」でアクセスできる
}

&uuのポインタを作っています。Go言語では、ポインタでもそのままptr.Nameのようにアクセスできます。

4. 関数にポインタを渡して値を変更する

4. 関数にポインタを渡して値を変更する
4. 関数にポインタを渡して値を変更する

構造体をポインタで関数に渡せば、中身を直接変更できます。


func updateAge(u *User) {
    u.Age = 30 // ポインタを通じて元の変数を変更
}

func main() {
    user := User{Name: "はなこ", Age: 20}
    updateAge(&user)
    fmt.Println(user.Age) // => 30
}

このように、*User型を引数にすることで、関数の中から直接データを更新できます。

5. new関数で構造体のポインタを作る方法

5. new関数で構造体のポインタを作る方法
5. new関数で構造体のポインタを作る方法

Go言語にはnew関数もあります。これを使うと、構造体のポインタを簡単に作成できます。


userPtr := new(User)
userPtr.Name = "じろう"
userPtr.Age = 18

newは、ゼロ値で初期化された構造体のポインタを返します。あとから値を代入すればOKです。

6. 構造体ポインタの応用:スライスと組み合わせる

6. 構造体ポインタの応用:スライスと組み合わせる
6. 構造体ポインタの応用:スライスと組み合わせる

構造体ポインタは、スライスと組み合わせて大量のデータを扱うときにも便利です。


users := []*User{
    &User{Name: "たろう", Age: 25},
    &User{Name: "はなこ", Age: 30},
    &User{Name: "じろう", Age: 22},
}

このように、スライスの中にポインタを入れることで、メモリの無駄を省きながら柔軟にデータを操作できます。

7. 値型とポインタ型の違いをまとめて整理

7. 値型とポインタ型の違いをまとめて整理
7. 値型とポインタ型の違いをまとめて整理
  • 値型:コピーされる。元のデータは変わらない。
  • ポインタ型:参照される。元のデータが直接変わる。

ポインタをうまく使えば、プログラムの効率も見た目のコードもスッキリさせることができます。

まとめ

まとめ
まとめ

Go言語の構造体とポインタについて学んできました。とくに初心者がつまずきやすいのが、値型とポインタ型の違いです。ふだんの変数は値そのものを持ちますが、ポインタは値の置かれている場所の情報を持っています。この違いを理解すると、構造体を扱うときに無駄なコピーを防いだり、関数の内側から元の値を直接変更したりすることができるようになります。プログラムは目に見えない世界ですが、住所と家の関係に置き換えると、ポインタは「家の場所」を教えてくれる存在だということが分かります。家の場所さえ分かれば、中にある家具を見たり並べ替えたりできます。まさにそれがポインタの役割なのです。

とくに構造体は、名前や年齢などの複数の情報をまとめて扱うため、小さなデータでもコピーを繰り返すとメモリが無駄になります。ポインタを使えばその負担を抑えることができ、大量のデータを処理するときにも効率よく動かせます。たとえば構造体を関数に渡す場合、値型で渡すと関数の中で変更しても外側には反映されません。しかしポインタで渡せば、関数の内側で書き換えた内容がそのまま呼び出し元に反映されます。この仕組みを知っておくと、データ更新が必要な場面で自然に使えるようになります。

さらにGo言語は、ポインタ経由であっても構造体のフィールドにそのまま「ドット記法」でアクセスできます。多くの言語ではポインタ用の記号を使ったり特別な書き方をしたりしますが、Go言語では自動で参照外しを行ってくれるため、とても読みやすく、初心者でも扱いやすい設計になっています。この働きのおかげで、ポインタを使う場面でもコードが複雑になりません。書き方のルールがシンプルなため、構造体とポインタの関係に慣れるほど「便利だな」と思えるようになります。

また、ポインタとスライスを組み合わせると、大量の構造体を無駄なく扱えます。実体をコピーするのではなく、場所だけを並べるので、どれだけデータが増えても負担が少なくなります。スライスから取り出したポインタを通じて値を変更すると、その変更は同じデータを参照しているすべての場所に反映されます。データの一覧を管理したり、条件に応じて変更したりといった処理の幅が広がるため、実用的なプログラムでも役立ちます。

簡単なサンプルを振り返る

値型で渡した場合と、ポインタで渡した場合の違いをもう一度確認しましょう。


type User struct {
    Name string
    Age  int
}

// 値型で受け取る(コピー)
func changeByValue(u User) {
    u.Age = 99
}

// ポインタで受け取る(実体)
func changeByPointer(u *User) {
    u.Age = 99
}

func main() {
    user := User{Name: "たろう", Age: 20}

    changeByValue(user)
    fmt.Println(user.Age) // 20(コピーが変わっただけ)

    changeByPointer(&user)
    fmt.Println(user.Age) // 99(実体が変更される)
}

どちらも同じ構造に見えますが、値型は別の入れ物を作ってそこだけが変わります。対してポインタは元の入れ物に直接触れるため、関数を抜けたあとにも結果が残ります。この違いを知っておくだけで、Go言語の構造体を扱うときの考え方が一気に分かりやすくなります。

先生と生徒の振り返り会話

生徒

「今日の内容で、ポインタがなんのために使われるのか分かった気がします。メモリの住所を持っているから、同じ変数をみんなで共有できるという感じですね。」

先生

「その通りです。同じ構造体を何度もコピーする必要がなくなるので、無駄な処理が減ります。とくに大量のデータを扱うとき、ポインタはとても役に立ちます。」

生徒

「関数に渡したときの違いも印象に残りました。値型だとコピーだけど、ポインタだと実体なんですね。」

先生

「はい。値型は安全に扱えますが、更新が必要ならポインタのほうが向いています。状況に応じて使い分けると良いですね。」

生徒

「あと、Go言語が自動で参照外しをしてくれるのがとても書きやすかったです。他の言語でポインタを触ったときは難しい印象があったので、ちょっと安心しました。」

先生

「読みやすさと扱いやすさはGo言語の魅力のひとつです。構造体とポインタを覚えるだけで、さまざまな処理を効率よく書けるようになりますよ。」

生徒

「今日の内容を踏まえて、今度はスライスとポインタを使ってデータの一覧を扱う練習もしてみたいです。」

先生

「とても良いですね。まずは小さなサンプルを作りながら、少しずつ慣れていきましょう。理解が深まると、より複雑なプログラムでも落ち着いて書けるようになります。」

生徒

「ありがとうございます!次の学習も楽しみです!」

この記事を読んだ人からの質問

この記事を読んだ人からの質問
この記事を読んだ人からの質問

プログラミング初心者からのよくある疑問/質問を解決します

Go言語の構造体にポインタを使う必要がある理由は何ですか?値渡しと参照渡しの違いがよく分かりません。

Go言語では構造体をそのまま関数に渡すと、メモリ上で別のコピーが作られます。これが値渡しです。大きな構造体をたくさんコピーすると、メモリを無駄に使い、処理速度も遅くなります。一方、ポインタを使った参照渡しであれば、構造体の値をコピーせず、メモリ上の同じデータを扱います。そのため、変更した結果が元の構造体に反映されるうえ、コピー処理が無いので効率が良くなります。プログラムのパフォーマンスやメモリ効率を良くしたいとき、Go言語の構造体とポインタを組み合わせることはとても重要です。
カテゴリの一覧へ
新着記事
New1
Kotlin
Kotlinの構文ルールまとめ!インデント・セミコロンなど初心者が最初に覚えるべきポイント
New2
Kotlin
Kotlinの関数ドキュメンテーションコメント(KDoc)の書き方を徹底解説!初心者でもわかる丁寧なガイド
New3
Kotlin
KotlinでHello Worldを表示するには?最初の1行を実行してみよう
New4
Go言語
Go言語の依存関係管理を始めよう!go modの基本設定と導入手順
人気記事
No.1
Java&Spring記事人気No1
Go言語
Go言語の関数パラメータ!値渡しと参照渡しの違いを理解しよう
No.2
Java&Spring記事人気No2
Kotlin
KotlinのAPI通信でGETリクエストを送る方法!初心者向け徹底ガイド
No.3
Java&Spring記事人気No3
Go言語
Go言語のテストでタイムアウト・並行処理を扱うポイント
No.4
Java&Spring記事人気No4
Swift
SwiftのURLSessionでのネットワークエラー対策!再試行とタイムアウトを初心者向けに解説
No.5
Java&Spring記事人気No5
Kotlin
Gradleファイル(build.gradle.kts)の書き方と役割をやさしく解説!Kotlin初心者向け完全ガイド
No.6
Java&Spring記事人気No6
Kotlin
Android Studioのインストール手順と初期設定を初心者向けに完全解説!
No.7
Java&Spring記事人気No7
Go言語
Go言語のWebアプリにおけるセキュリティベストプラクティス集
No.8
Java&Spring記事人気No8
Swift
Swift JSONデコード失敗の原因と対処|DecodingError徹底解説