13. ポインタ
13.1 メモリとアドレス
ポインタの話にはいる前に、まずはGoのメモリとアドレスについてお話しします。
メモリには変数を入れる領域が確保され、メモリの領域にアドレスが割り振られています。
Goではアドレス演算子 “&” を利用し、変数のアドレスを確認することが出来ます。
※例のアドレスは固定値ではなく、実行する環境やタイミングによって値が変わります。
var a int a = 1 var b int b = 2 var c int c = 3 fmt.Println(a) //"1"が出力される fmt.Println(b) //"2"が出力される fmt.Println(c) //"3"が出力される fmt.Println(&a) //"0x1040e0f8"が出力される fmt.Println(&b) //"0x1040e0fc"が出力される fmt.Println(&c) //"0x1040e130"が出力される
このとき、アドレスと値は次の図のような状態です。
13.2 アドレスとポインタ
Goにはアドレスを格納できる「ポインタ」があります。
また、アドレス演算子 “&” を利用し、アドレスが示す値を参照できます。
先ほどのコードにポインタの変数dを追加で定義します。
var a int a = 1 var b int b = 2 var c int c = 3 // 型の前に ”*” をつけるとポインタとなります。 var d *int // ポインタのint型の変数dに、aのアドレスを代入します d = &a fmt.Println(a) //"1"が出力される fmt.Println(b) //"2"が出力される fmt.Println(c) //"3"が出力される fmt.Println(&a) //"0x1040e0f8"が出力される fmt.Println(&b) //"0x1040e0fc"が出力される fmt.Println(&c) //"0x1040e130"が出力される fmt.Println(d) //"0x1040e0f8"が出力される fmt.Println(&d) //"0x1040a120"が出力される fmt.Println(*d) //"1"が出力される
このとき、メモリとアドレスと値は次の図のような状態になります。
fmt.Println(d)
aのアドレスである"0x1040e0f8"が出力されます。
dの値 には aのアドレス が格納されています。
fmt.Println(&d)
dのアドレスである"0x1040a120"が出力されます。
d自身のアドレスです。
fmt.Println(*d)
aの値である"1"が出力されます。
“*” を使用することで、dに格納されたアドレスからaの値を参照しています。
このとき、aの値が変わると*dの値も変わります。
var a int a = 1 var b int b = 2 var c int c = 3 // 型の前に ”*” をつけるとポインタとなります。 var d *int // ポインタのint型の変数dに、aのアドレスを代入します d = &a fmt.Println(a) //"1"が出力される fmt.Println(b) //"2"が出力される fmt.Println(c) //"3"が出力される fmt.Println(&a) //"0x1040e0f8"が出力される fmt.Println(&b) //"0x1040e0fc"が出力される fmt.Println(&c) //"0x1040e130"が出力される fmt.Println(d) //"0x1040e0f8"が出力される fmt.Println(&d) //"0x1040a120"が出力される fmt.Println(*d) //"1"が出力される a += 1 //aの値に"1"を加える fmt.Println(a) //"2"が出力される fmt.Println(*d) //aの値が"2"になったので"2"が出力される