【GO】Golangの勉強を始めたから殴り書きのメモ~その2
つづき。 tour.golang.org
Pointer
ポインタは値のメモリアドレスを指す。→ 値が保存されてる場所
- 定義
// ゼロ値は nil var p *int
package main import "fmt" func main() { i, j := 42, 2701 p := &i // pにiのポインタを代入 fmt.Println(p) // 0x40e020 // iのポインタを通して、値を取得 fmt.Println(*p) // 42 // iのポインタを通して、値をセット *p = 21 // メモリアドレスの値が変更されたからiの値も変わる fmt.Println(i) // 21 p = &j // pにjのポインタを代入 *p = *p / 37 // jのポインタを通して、値を更新 fmt.Println(j) // 73 }
Structs
struct (構造体)は、フィールド( field )の集まり。
package main import "fmt" type Vertex struct { X int Y int } func main() { fmt.Println(Vertex{1, 2}) }
ドットつなぎでアクセスできるよ
package main import "fmt" // 構造体ってやつを定義 type Vertex struct { // 構造体を持つフィールドを定義 X int Y int } func main() { v := Vertex{1, 2} fmt.Println(v.X) // 1 v.X = 4 fmt.Println(v.X) // 4 }
構造体のポインタ
package main import "fmt" type Vertex struct { X int Y int } func main() { v := Vertex{1, 2} p := &v // vのポインタを代入 p.X = 1e9 // 本来は(*p).Xのように書けるが、p.Xで同じ意味になる fmt.Println(v) // {1000000000 2} }
初期値の割り当て
package main import "fmt" type Vertex struct { X, Y int } var ( v1 = Vertex{1, 2} // 普通に v2 = Vertex{X: 1} // Xだけ v3 = Vertex{} // 両方入れない p = &Vertex{1, 2} // &をつけるとポインタ ) func main() { fmt.Println(v1, p, v2, v3) // {1 2} &{1 2} {1 0} {0 0} }
Arrays
宣言と代入
package main import "fmt" func main() { // 配列は固定長 var a [2]string // string型の2個の変数の配列を宣言 a[0] = "Hello" a[1] = "World" fmt.Println(a[0], a[1]) // Hello World fmt.Println(a) // [Hello World] // 宣言と代入 primes := [6]int{2, 3, 5, 7, 11, 13} // [2 3 5 7 11 13] fmt.Println(primes) }
Slices
package main import "fmt" func main() { // スライスは可変長 primes := [6]int{2, 3, 5, 7, 11, 13} // [low:high]を指定するよ var s []int = primes[1:4] fmt.Println(s) // [3 5 7] }
- スライスは配列への参照
package main import "fmt" func main() { // 配列を生成 names := [4]string{ "John", "Paul", "George", "Ringo", } fmt.Println(names) // [John Paul George Ringo] a := names[0:2] b := names[1:3] fmt.Println(a, b) // [John Paul] [Paul George] b[0] = "XXX" fmt.Println(a, b) // [John XXX] [XXX George] // 配列の値も変更される(=スライスは配列への参照) fmt.Println(names) // [John XXX George Ringo] }
- スライスのいろんな宣言と代入
package main import "fmt" func main() { q := []int{2, 3, 5, 7, 11, 13} fmt.Println(q) r := []bool{true, false, true, true, false, true} fmt.Println(r) s := []struct { i int b bool }{ {2, true}, {3, false}, {5, true}, {7, true}, {11, false}, {13, true}, } fmt.Println(s) }
- ちょっと変わった定義
package main import "fmt" func main() { s := []int{2, 3, 5, 7, 11, 13} // 普通に s = s[1:4] fmt.Println(s) // [3 5 7] // 下限を指定しない s = s[:2] fmt.Println(s) // [3 5] // 上限も下限を指定しない s = s[:] fmt.Println(s) // [3 5] }
- 長さ(length)と容量(capacity)
package main import "fmt" func main() { s := []int{2, 3, 5, 7, 11, 13} printSlice(s) // len=6 cap=6 [2 3 5 7 11 13] // Slice the slice to give it zero length. s = s[:0] printSlice(s) // len=0 cap=6 [] // Extend its length. s = s[:4] printSlice(s) // len=4 cap=6 [2 3 5 7] // Drop its first two values. s = s[2:] printSlice(s) // len=2 cap=4 [5 7] var s2 []int // スライスのゼロ値は[] fmt.Println(s2, len(s2), cap(s2)) // [] 0 0 if s2 == nil { fmt.Println("nil!") } } func printSlice(s []int) { fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s) }
- make関数を使ってスライスを作る
package main import "fmt" func main() { // 長さが5のスライス a := make([]int, 5) printSlice("a", a) // a len=5 cap=5 [0 0 0 0 0] // 長さ0,容量5のスライス b := make([]int, 0, 5) printSlice("b", b) // b len=0 cap=5 [] c := b[:2] printSlice("c", c) // c len=2 cap=5 [0 0] d := c[2:5] printSlice("d", d) // d len=3 cap=3 [0 0 0] } func printSlice(s string, x []int) { fmt.Printf("%s len=%d cap=%d %v\n", s, len(x), cap(x), x) }
- スライスに要素を追加
package main import "fmt" func main() { var s []int printSlice(s) // len=0 cap=0 [] // append works on nil slices. // 第一引数が加える元、第二引数以降は可変長の加える変数 s = append(s, 0) printSlice(s) // len=1 cap=2 [0] // The slice grows as needed. s = append(s, 1) printSlice(s) // len=2 cap=2 [0 1] // We can add more than one element at a time. s = append(s, 2, 3, 4) printSlice(s) // len=5 cap=8 [0 1 2 3 4] } func printSlice(s []int) { fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s) }
- Range
package main import "fmt" var pow = []int{1, 2, 4, 8, 16, 32, 64, 128} func main() { // iはインデックス。vはその要素。 for i, v := range pow { fmt.Printf("2**%d = %d\n", i, v) } }
- 代入しない
package main import "fmt" func main() { pow := make([]int, 10) // ", v"を書かなければ代入を行わない for i := range pow { pow[i] = 1 << uint(i) // == 2**i } // "_"で代入を行わない for _, value := range pow { fmt.Printf("%d\n", value) } }
Map
package main import "fmt" type Vertex struct { Lat, Long float64 } var m map[string]Vertex func main() { // make関数を使ってMapを作成 m = make(map[string]Vertex) m["Bell Labs"] = Vertex{ 40.68433, -74.39967, } fmt.Println(m["Bell Labs"]) // {40.68433 -74.39967} }
package main import "fmt" type Vertex struct { Lat, Long float64 } // mapリテラル var m = map[string]Vertex{ "Bell Labs": Vertex{ 40.68433, -74.39967, }, "Google": Vertex{ 37.42202, -122.08408, }, } func main() { fmt.Println(m) // map[Bell Labs:{40.68433 -74.39967} Google:{37.42202 -122.08408}] }
package main import "fmt" type Vertex struct { Lat, Long float64 } // さらに省略 var m = map[string]Vertex{ "Bell Labs": {40.68433, -74.39967}, "Google": {37.42202, -122.08408}, } func main() { fmt.Println(m) }
- マップの操作
package main import "fmt" func main() { // make関数でmapを作る m := make(map[string]int) m["Answer"] = 42 fmt.Println("The value:", m["Answer"]) // The value: 42 // 上書き m["Answer"] = 48 fmt.Println("The value:", m["Answer"]) // The value: 48 // 要素を消す delete(m, "Answer") // valueのゼロ値が入る fmt.Println("The value:", m["Answer"]) // The value: 0 // キーに対する要素が存在するかどうかは、2つの目の値で返す v, ok := m["Answer"] fmt.Println("The value:", v, "Present?", ok) // The value: 0 Present? false }
package main import ( "fmt" "math" ) func compute(fn func(float64, float64) float64) float64 { return fn(3, 4) } func main() { // 関数に関数を渡せる // 関数も変数として扱える hypot := func(x, y float64) float64 { return math.Sqrt(x*x + y*y) } fmt.Println(hypot(5, 12)) // 13 fmt.Println(compute(hypot)) // 5 fmt.Println(compute(math.Pow)) // 81 }