ポインタは、値そのものではなく値のメモリアドレスを保持します。Go はポインタ (C のように) を持っていますが、シンプルで安全に保っています — ポインタ演算なし、ガベージコレクタがメモリを管理します。データを効率的に共有および変更するために使用されます。
なぜ重要なのか: 2 つの演算子 & と *
go
x :=
p := &x
fmt.Println(p)
fmt.Println(*p)
*p =
fmt.Println(x)
& は変数のアドレスを取得します。* (ポインタ上の) は、ポインタが指している値にアクセスまたは設定します。
// ❌ value parameter — the function gets a COPY; changes don't affect the caller
func incrementValue(n int) { n++ } // caller's variable unchanged
// ✅ pointer parameter — the function can modify the caller's variable
func incrementPointer(n *int) { *n++ }
x := 5
incrementValue(x) // x still 5
incrementPointer(&x) // x is now 6
Go は引数を値で渡す (コピー) ため、関数がコールアドレスのデータを変更できるのは、そのデータへのポインタを受け取った場合のみです。これがポインタを使用する主な理由です。
type Counter struct { count int }
// pointer receiver → method can modify the struct
func (c *Counter) Increment() { c.count++ }
c := &Counter{} // a pointer to a Counter
c.Increment() // modifies it (Go auto-dereferences: (*c).count++)
ポインタレシーバーは、メソッドが構造体を変更する方法です。構造体ポインタを渡すことで、大きな構造体のコピーが避けられます。
var p *int // zero value of a pointer is nil
fmt.Println(p) // <nil>
*p = 5 // 💥 PANIC: nil pointer dereference (no value to point to)
if p != nil { *p = 5 } // guard against nil
nil ポインタを逆参照するとパニックになります — 防ぐべき一般的なランタイムエラーです。
✗ NO pointer arithmetic (can't do p++ to move through memory like C)
✗ NO manual free — garbage collector reclaims memory
→ Pointers are about sharing/modifying data, not low-level memory hacking
ポインタは Go で 2 つの主な目的に不可欠です。1 つ目は、コールアドレスのデータを変更すること (Go は値で渡すため、関数が元のデータを変更できるのはポインタだけです) です。2 つ目は効率です (ポインタを渡すことで大きな構造体のコピーが回避されます)。
ポインタレシーバーを持つメソッド (構造体を変更する標準的な方法) には不可欠であり、慣例的な Go 全体に表示されます。
&/*、値対ポインタセマンティクス、nil ポインタパニック、および Go ポインタが意図的に安全 (演算なし、GC 管理) — C スタイルのメモリ操作ではなく共有/変更に焦点を当てている — を理解することは、正確で効率的な Go を記述するための中核的な知識であり、初心者やインタビューでよくある混乱の一点です。