Go のポインター
Go のポインターの説明
ポインター
ポインターは変数が格納されているメモリーアドレスを保持する。C 言語と同様に、オブジェクトのアドレスを取得するには & を使い、ポインターが参照する値へアクセスするには * を使う。
package main
import "fmt"
func main() {
var a1 int // int 型の変数 a1 を定義する
var p1 *int // int 型へのポインター変数 p1 を定義する
p1 = &a1 // p1 に a1 のアドレスを格納する
*p1 = 123 // 参照先、つまり a1 に 123 を代入する
fmt.Println(a1)
fmt.Println(p1)
fmt.Println(*p1)
}
実行結果:
123
0xc00001c030
123
変数の値を渡すことを値渡しと呼ぶ。変数へのポインターを渡すと、関数から参照先の変数へアクセスできる。値渡しでは値のコピーだけが渡されるため、元の変数を変更できない。ポインターを渡すと、関数から変数を変更できる。
package main
import "fmt"
func main() {
var a1 int = 123
var a2 int = 123
fn(a1, &a2) // a1 は値を渡し、a2 はアドレスを渡す
fmt.Println(a1, a2)
}
func fn(b1 int, b2 *int) {
b1 = 456
*b2 = 456
}
実行結果:
123 456
. 演算子を使うと、構造体の値と構造体へのポインターのどちらからでもフィールドへアクセスできる。
package main
import "fmt"
type Person struct {
name string
age int
}
func main() {
a1 := Person{"devkuma", 23} // Person の値を作成して初期化する
p1 := &a1 // a1 へのポインターを p1 に格納する
fmt.Println(a1.name) // 値からフィールドへアクセスする
fmt.Println((*p1).name) // ポインターをデリファレンスしてフィールドへアクセスする
fmt.Println(p1.name) // Go ではこの短い形式も使用できる
}
実行結果:
devkuma
devkuma
devkuma
領域の確保(new)
new() を使うと領域を動的に確保し、その領域へのポインターを取得できる。確保した領域は参照されなくなると、Go のガベージコレクターによって自動的に解放される。
package main
import "fmt"
type Book struct {
title string
}
func main() {
bookList := []*Book{}
for i := 0; i < 10; i++ {
book := new(Book)
book.title = fmt.Sprintf("Title#%d", i)
bookList = append(bookList, book)
}
for _, book := range bookList {
fmt.Println(book.title)
}
}
実行結果:
Title#0
Title#1
Title#2
Title#3
Title#4
Title#5
Title#6
Title#7
Title#8
Title#9