Go についてのメモ

package main
import "fmt"
import "reflect"

type Arr [5]int

func main() {
    a := Arr{1, 2, 3}    //配列
    b := Arr{7, 8, 9}    //配列
    c := append(a[:], b[:]...)    //append の引数にはスライスしか取らない
    fmt.Println(c)
    fmt.Println(reflect.ValueOf(c).Kind())
}
//=>[1 2 3 0 0 7 8 9 0 0]
//=>slice

package main
import "fmt"

func main() {
    a := [6]int{1, 2, 3, 4, 5, 6}
    b := a[1:3]
    fmt.Println(b)    //=>[2 3]
    b = b[0:5]
    fmt.Println(b)    //=>[2 3 4 5 6]
}

 
変数に nil は代入できない。

func main() {
    var a int
    a = nil
    fmt.Println(a)
}

コンパイル・エラー。

こういうことは可能。type A struct の中に A を使っているが、*A はポインタなので構造体の再帰的定義(エラーになる)にならない。

package main
import "fmt"

type A struct {
    value string
    parent *A
}


func main() {
    oya    := &A{"のらの親", &A{}}
    nora   := &A{"のら",    oya}
    konora := &A{"子のら",  nora}
    for a := konora; (*a).parent != nil; a = (*a).parent {
        fmt.Println((*a).value)
    }
}
//(*a) はすべて a と省略して書ける

実行。親を遡っていく。

$ go run a.go
子のら
のら
のらの親

 
例えばサブルーチンでカウントする。このとき、構造体は値渡しなので、以下は期待した動作をしない。

package main
import "fmt"

type A struct {
    value int
}

func count(n A) {
    n.value++
}

func main() {
    x := A{value: 1}
    count(x)
    fmt.Println(x.value)    //=>1
}

正しくは構造体のポインタを渡さないといけない。

package main
import "fmt"

type A struct {
    value int
}

func count(n *A) {
    n.value++    //(*n).value++のシンタックスシュガー
}

func main() {
    x := &A{value: 1}
    count(x)
    fmt.Println(x.value)    //=>2
}

代入の場合も同様。y := x の代入時にコピーされる。

package main
import "fmt"

type A struct {
    value int
}

func main() {
    x := A{value: 1}
    y := x
    y.value++
    fmt.Println(y.value)    //=>2
    fmt.Println(x.value)    //=>1
}

Go は基本的に破壊的変更をしづらいようになっているのだな。破壊的変更はポインタでやる。ただし、もちろん参照型は別。