Go ポインタ編
Go ポインタ編
ポインタ
package main import "fmt" func main(){ var n int = 100 fmt.Println(n) // 100 // &(アンパサンド)はメモリのアドレスを表す fmt.Println(&n) // >>> 0xc00001a040 (変数nのメモリアドレス) // *intでポインタ変数の定義ができ、変数への格納はメモリアドレスを渡す var p *int = &n fmt.Println(p) // >>> 0xc00001a040 // *ポインタ変数 で実体値にアクセスできる(デリファレンスと読んだりもする) fmt.Println(*p) // 100 }
*デリファレンス(dereference)
何かを参照しているものの参照先を見に行くこと。
変数とポインタ変数の挙動の違い
func one(x int){ x = 1 } func main(){ var n int = 100 one(n) // func oneでは書き換えが行われずに100 fmt.Println(n) // >>> 100 }
func two(x *int){ *x = 1 // *xで実体(n)にアクセスし書き換え } func main(){ var n int = 100 two(&n) // 変数nのメモリのアドレスを渡す fmt.Println(n) // >>> 1 }
new
値を入れずにメモリにアドレスだけを確保したい場合はnewを使う
package main import "fmt" func main(){ // メモリにアドレスだけを確保したい場合はnewを使う var p *int = new(int) fmt.Println(p) // >>>0xc0000a0000 // 中身の実体値は0が入っている fmt.Println(p) // >>> 0 // newをしない場合はポインタ型変数の宣言をしてもメモリを確保がされていない var p2 *int fmt.Println(p2) // >>> nil // 中身を確認すると panicでerrorが返却される fmt.Println(*p2) }
struct
package main import "fmt" // capital paburiku // プライベートになる type Vertex struct{ X int Y int } func main() { v := Vertex{X:1, Y:2} fmt.Println(v) // vの中にもアクセスできる fmt.Println(v.X, v.Y) // 中身の書き換え v.X = 100 fmt.Println(v.X, v.Y) type Vertex2 struct{ X int Y int S string }
func main() { v := Vertex{X:1, Y:2} fmt.Println(v) // vの中にもアクセスできる fmt.Println(v.X, v.Y) // 中身の書き換え v.X = 100 fmt.Println(v.X, v.Y) // 指定していなければデフォルトのint 0が挿入される(stringであれば空) v2 := Vertex{X: 1} fmt.Println(v2) // >>> {1 0} // structの中身を指定しない場合は順番通り入れればOK v3 := Vertex2{1, 2, "test"} fmt.Println(v3) // >>> {1 2 test} // 全て指定しなければデフォルトで返却される v4 := Vertex2{} fmt.Println(v4) // >>> {0 0 } fmt.Printf("%T %v\n", v4, v4) // nilにはならない sliceやmapはnilになる var v5 Vertex2 fmt.Printf("%T %v\n", v5, v5) v6 :=new(Vertex2) fmt.Printf("%T %v\n", v6, v6) // pointerが帰ってきている v7 := &Vertex2{} // こっちを使う人の方が多い気がする fmt.Printf("%T %v\n", v7, v7) // pointerが帰ってきている s := []int{} s := []int{} }