忙しい人のためのA Tour of Go


Go Conference 2013 Springのハンズオンで[A Tour of Go](http://go-tour-jp.appspot.com/)やったけど目で読んでも頭に入ってこないのでメモりながらやった。

ちょっとしたまとめページになったのでさらっとよんで感触をつかむときには役に立つかもしれないけど、結局は演習などでコード書かないと身につかないことがわかったので時間をつくってちゃんとやった方がいいと思う。

## Packages

* すべてのプログラムは ``package`` で構成される
* プログラムの処理は ``main`` パッケージの ``main`` 関数で始まる
* 他のパッケージは ``import`` で取り込める
* ``import "websocket"``のwebsoketは``code.google.com/p/go.net/websocket``を指している

## Imports

* ``import`` は括弧でグループすることができる

```go
import "fmt"
import "math"
```

↓

```go
import (
    "fmt"
    "math"
)
```

## Exported names

* インポートしたパッケージが外部に公開(Export)している名前を参照できる
* 公開する名前は最初の文字が大文字になっている ```math.Pi```

## Functions

* 関数は0個以上の引数を取ることができる
* 変数、戻り値の型は後ろに来る ```func add(x int, y int) int```
 * 理由は[Go's Declaration Syntax](http://golang.org/doc/articles/gos_declaration_syntax.html)を参照


## Functions continued

* 同じ型の引数の場合は最後の型だけ残して省略できる ``func add(x, y int) int``

## Multiple results

* 関数は複数の戻り値を返すことができる

```go
func swap(x, y string) (string, string) {
    return y, x
}
func main() {
    a, b := swap("hello", "world")
    fmt.Println(a, b)
}
```

## Named results

* 複数の戻り値は名前付きで宣言しておくと ``return`` だけで返せる

```go
func split(sum int) (x, y int) {
    x = sum * 4 / 9
    y = sum - x
    return
}
func main() {
    fmt.Println(split(17))
}
```

## Variables

* ``var`` を変数の宣言に使える
* 同じ型が連続する場合は最後以外は省略可能

```go
var x, y, z int
var c, python, java bool
```

## Variables with initializers

* ``var`` 宣言では、変数ひとつひとつに初期値を渡せる ``var x, y, z int = 1, 2, 3``
* 初期値によって型を省略することができそのリテラルの型になる ``var c, python, java = true, false, "no!"``

## Short variable declarations

* 関数内では ``var`` 宣言の代わりに、暗黙的な型宣言ができる ``:=`` の代入文を使うことができる ``c, python, java := true, false, "no!"``

## Basic types

* 基本型（組み込み型）

```go
bool
string
int  int8  int16  int32  int64
uint uint8 uint16 uint32 uint64 uintptr
byte // uint8 の別名
rune // int32 の別名
     // Unicode のコードポイントを表す
float32 float64
complex64 complex128
```

## Constants, Numeric Constants

* ``const`` キーワードを使い定数を宣言できる ``const Pi = 3.14``
* 型としてはcharacter、string、boolean、数値(numeric)のみで使える
* 数値定数は高精度な値である
* 型のない定数は、その状況によって必要な型を取る

## For

* 繰り返し文は ``for`` だけで while文 はない
* 括弧 ``()`` は不要で中括弧 ``{}`` は必要

```go
    sum := 0
    for i := 0; i < 10; i++ {
        sum += i
    }
```

## For continued, For is Go's "while"

* ``for`` の条件の前後は省略可能 ``for sum < 1000 {}``
* ``;`` も省略できるのでこれが while の代わりになる
* ループ条件も省略して ``for {} `` にすれば無限ループになる

## If, If with a short statement, If and else

* ``if`` は 括弧 ``()`` は不要で中括弧 ``{} ``は必要 ``if x < 0 {}``
* ``if`` も ``for`` のように条件の前にステートメントを記述できる ``if v := math.Pow(x, n); v < lim {}``
* そのステートメントで宣言された変数は ``if`` および ``else`` ブロック内で有効になる

## Structs, Struct Fields

* 構造体 ``struct`` はフィールドの集まり
* フィールドは ``.`` でアクセスする ``v.X = 4``
* ``type`` 宣言できる

```go
type Vertex struct {
    X int
    Y int
}
Vertex{1, 2}
```

## Pointers

* ポインタはあるがポインタ演算はない
* 構造体のポインタを渡して ``.`` でフィールドにアクセスできる

```go
p := Vertex{1, 2}
q := &p
q.X = 1e9
```

## Struct Literals

* ``struct`` リテラルは ``Name:`` 構文を使って初期化できる ``r = Vertex{X: 1}``
* ``Name:`` 構文を使った場合は指定順序は無関係になる
* 接頭辞 ``&`` は ``struct`` リテラルへのポインタを示す ``q = &Vertex{1, 2}``

## The new function

* ``new(T)`` という表現は、ゼロ初期化した ``T`` の値をメモリに割り当て、そのポインタを返す
* ``var t *T = new(T)`` または ``t := new(T)`` と書ける 

## Slices

* Goの配列表現sliceは値の配列を参照し、長さも含む
* ``T`` 型要素のsliceは ``[]T `` となる ``p := []int{2, 3, 5, 7, 11, 13}``

## Slicing slices

* ``s[lo:hi]``のように範囲を指定してsliceからsliceを作成できる

```go
p == [2 3 5 7 11 13]
p[1:4] == [3 5 7]
p[:3] == [2 3 5]
p[4:] == [11 13]
```

## Making slices

* ``make`` 関数はゼロ初期化した配列をメモリに割り当て、その配列を参照したsliceを返す ``a := make([]int, 5)``
* sliceは、長さと容量を持っており、容量より長くすることはできない
* 長さは ``len(a)`` 容量は ``cap(a)`` 関数をつかって調べられる
* 容量を指定するには ``make`` の **3** 番目の引数を使う ``b := make([]int, 0, 5) // len(b)=0, cap(b)=5``
 * 省略した場合、容量は長さと同じになる
* 容量はre-slicingによって縮小することがある

## Nil slices

* ``var z []int`` などで宣言したsliceの初期値は ``nil`` 
* ``nil``な sliceの長さと容量を ``len(z), cap(z)`` で計算した時の値は **0** である

## Range

* ``for`` ループの ``range`` はsliceやmapを1つずつ反復処理する
* あとからでてくるチャネルからも1つずつ処理できる

```go
var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}
func main() {
    for i, v := range pow {
        fmt.Printf("2**%d = %d\n", i, v)
    }
}
```

## Range continued

* ``range`` で受け取ったインデックスや値を使わない場合は ``_`` へ代入することで破棄することができる

```go
    for _, value := range pow {
        fmt.Printf("%d\n", value)
    }
    for i, _ := range pow {
        fmt.Printf("%d\n", pow[i])
    }
```

## Maps

* map はキーと値とを関連付ける ``var m map[string]Vertex``
* mapはsliceでも使った ``make`` 関数で作成する
* makeで作成するまでの ``nil`` のmapは空なので要素を割り当てられない ``m = make(map[string]Vertex)``

## Map literals, Map literals continued

* mapリテラルは、structリテラルに似ているがキーが必要
* ``string`` がキーで、``struct`` が値のmapのリテラルは以下のようになる

```go
type Vertex struct {
    Lat, Long float64
}
var m = map[string]Vertex{
    "Bell Labs": Vertex{
        40.68433, -74.39967,
    },
    "Google": Vertex{
        37.42202, -122.08408,
    },
}
```

* リテラルの要素から型が推定できる場合は型名を以下のように省略可能

```go
var m = map[string]Vertex{
    "Bell Labs": {40.68433, -74.39967},
    "Google":    {37.42202, -122.08408},
}
```

## Mutating Maps

* map ``m`` へ要素(elem)の挿入や更新は：``m[key] = elem``
* 要素の取り出しは：``elem = m[key]``
* 要素の削除は：``delete(m, key)``
* キーが存在するかどうかは、２つの値の代入で確認する ``elem, ok = m[key]``
 * キーが存在しない場合は ok は ``false`` になり、elemは要素の型のゼロ値になる


## Function values

* 関数も変数として扱える ``hypot := func(x, y float64) float64 { return math.Sqrt(x*x + y*y) }``
* 関数そのものを関数の引数とすることもできる

## Function closures

* 関数はclosureである
* 関数が変数として代入されたスコープの関数外の変数を使える

## Switch, Switch evaluation order

* ``switch`` は ``case`` の最後で自動的にbreakする
* ``case`` には式も書けて上から下へ ``case`` を評価する
* brakeせずに次の ``case`` のブロックへ通したい場合は``fallthrough``を入れる

```go
   case "linux":
        fmt.Println("Linux.")
        fallthrough
```

## Switch with no condition

* 条件のない ``switch`` は ``switch true`` と同じになる
* 長いif-then-elseのつながりをシンプルに表現できる

```go:
    t := time.Now()
    switch {
    case t.Hour() < 12:
        fmt.Println("Good morning!")
    case t.Hour() < 17:
        fmt.Println("Good afternoon.")
    default:
        fmt.Println("Good evening.")
    }
```

## Methods, Methods with pointer receivers

* Goにはクラスはないが ``struct`` にメソッドを定義できる
* メソッドレシーバを ``func`` キーワードとメソッド名の間で、それ自身の引数リストで表現する (下記の例では ``(v *Vertex)`` )

```go
type Vertex struct {
    X, Y float64
}
// Vertex.Absメソッド
func (v *Vertex) Abs() float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
func main() {
    v := &Vertex{3, 4}
    fmt.Println(v.Abs())
}
```

* ポインタのメソッドレシーバを使うのはメソッド呼び出し時に値をコピーによるオーバヘッドを避けるためと``struct`` のフィールドの内容を更新するためがある

## Methods continued

* ``struct`` だけではなくパッケージ内で任意の型にもメソッドを定義できる
* ただし他のパッケージからの型や基本型 **以外** に限る

```go
type MyFloat float64
func (f MyFloat) Abs() float64 {
    if f < 0 {
        return float64(-f)
    }
    return float64(f)
}
func main() {
    f := MyFloat(-math.Sqrt2)
    fmt.Println(f.Abs())
}
```

## Interfaces

* インターフェース型はメソッド群を定義する
* インターフェース型で宣言した変数は、それらのメソッドを実装する型の値を持つことができる

```go
type Abser interface {
    Abs() float64
}
```

## Interfaces are satisfied implicitly

* 型は（インターフェース型が定義した）メソッドを実装することでインターフェースを実装したことになり、明示的にインターフェースを持っていることを定義する必要がない
* この暗黙的なインターフェースはインターフェースを定義するパッケージから実装するパッケージを分離することができ、他に依存しない
* インタフェースのすべての実装を見つける必要もないし、新しいインターフェースの名前でそのインタフェースを関連付ける必要もないので、正確なインターフェースの定義を推奨する

## Errors

* エラーは文字列でエラーそのものを説明する
* ``error`` インターフェースの ``Error`` メソッドを定義することで表現する

```go
type error interface {
	Error() string
}
```


```go
type MyError struct {
    When time.Time
    What string
}
func (e *MyError) Error() string {
    return fmt.Sprintf("at %v, %s",
        e.When, e.What)
}
```


## Web servers

* ``http`` パッケージはHTTPリクエストの処理を行うための``http.Handler`` インターフェースを定義する
* ``http.Handler`` インターフェースを実装することで HTTPリクエストの処理機能を提供することができる

```go
type Hello struct{}
func (h Hello) ServeHTTP(
    w http.ResponseWriter,
    r *http.Request) {
    fmt.Fprint(w, "Hello!")
}
func main() {
    var h Hello
    http.ListenAndServe("localhost:4000", h)
}
```

## Images

* ``image`` パッケージは、以下の ``Image`` インターフェースを定義する

```go
package image
type Image interface {
	ColorModel() color.Model
	Bounds() Rectangle
	At(x, y int) color.Color
}
```


* 詳細は [ドキュメント](http://golang.org/pkg/image/#Image) を参照
* ``color.Color`` と ``color.Model`` は共にインターフェースで、実装としては定義済みの ``color.RGBA`` と ``color.RGBAModel`` を使うことができる

## Goroutines

* goroutineは、Goのランタイムに管理される軽量なスレッド、``main`` 関数もgoroutineで実行される
* ``main`` 関数のgoroutineの処理が終わると他のgroutineが実行中でもプロセスが終了する
* ``go f(x, y, z)``と書くと 関数f は新しいgoroutine上で実行される
* x,y,zの値の評価は現在のgoroutineで発生しfの実行は、新しいgoroutineで行われる
* goroutineは同じアドレス空間で実行されるため、共有メモリへのアクセスはきちんと同期する必要がある
* 同期の方法に[sync](http://golang.org/pkg/sync/) パッケージがあるが、Goでは以降の章のものがあるのであまり必要されない

## Channels

* チャネルはチャネルオペレータの <- を用いて値の送受信ができる直通ルートの型
* ``map``, ``slice``と同じく ``make`` 関数で生成する ``ch := make(chan int)``
* 送受信する値の型の前に ``chan`` をつける
* デフォルトでは片方が準備できるまで送受信はブロックする(goroutineの処理がそこで止まる)
* これは明確なロックや条件変数がなくてもgoroutineの同期を許す
* データは矢印の方向に流れる

```go
ch <- v    // v をチャネル ch へ送る。
v := <-ch  // ch から受信し、
           // 変数を v へ割り当てる
```

```go
func sum(a []int, c chan int) {
    sum := 0
    for _, v := range a {
        sum += v
    }
    c <- sum // send sum to c
}
func main() {
    a := []int{7, 2, 8, -9, 4, 0}
    c := make(chan int)
    go sum(a[:len(a)/2], c)
    go sum(a[len(a)/2:], c)
    x, y := <-c, <-c // receive from c
    fmt.Println(x, y, x+y)
}
```

## Buffered Channels

* チャネルはバッファでき、送信した値をためておける
* ``make`` 関数の第2引数でバッファの長さを指定できる ``ch := make(chan int, 100)``
* バッファがいっぱいになったチャネルへの送信はブロックする
* バッファが空のチャネルには受信をブロックする

```go
func main() {
    c := make(chan int, 2)
    c <- 1
    c <- 2 // バッファがいっぱいになる
    c <- 3 // バッファがいっぱいなので送信がブロックされmainのgoroutinesが止まりデットロック
    fmt.Println(<-c)
    fmt.Println(<-c)
}
```

## Range and Close

* 送り手はこれ以上の送信する値がないことを示すため ``close(ch)`` でチャネルを閉じることができる
* 受け手は受信の式の2つ目のパラメータが ``false`` かどうかで送り手が閉じたかどうかをテストできる ``v, ok := <-ch``
* ``for i := range c`` はチャネル ``c`` が閉じるまで繰り返し値を受信する
* 閉じたチャネルに送信するとpanicになるため受け手が勝手にチャネルを閉じると危険である
* チャネルは通常は閉じなくてよい
* チャネルを閉じないといけないの ``range`` ループなどで受け手が送信側の終了を判断しないといけないとき

## Select

* ``select`` ステートメントはgoroutineを複数の通信操作で待たせる
* ``select`` は ``case`` の条件で通信が実行できるまでブロックし、条件が一致すれば ``case`` の中の処理を実行する
* 以下の例では ``main`` 関数と無名関数を処理する２つのgoroutineがあり、``main`` 側のgoroutineは ``func fibonacci`` 内の ``select`` でブロックする。無名関数を処理するgoroutineが ``c`` からの受信、``quite`` の送信を行うことと ``main`` 側のgoroutineで ``case`` 内の処理が実行され、 ``quite`` を受信した際に ``return`` し、``main`` 関数のgoroutineが処理を終える

```go
func fibonacci(c, quit chan int) {
    x, y := 0, 1
    for {
        select {
        case c <- x:
            x, y = y, x+y
        case <-quit:
            fmt.Println("quit")
            return
        }
    }
}
func main() {
    c := make(chan int)
    quit := make(chan int)
    go func() {
        for i := 0; i < 10; i++ {
            fmt.Println(<-c)
        }
        quit <- 0
    }()
    fibonacci(c, quit)
}
```

## Default Selection

* ``select`` を評価したときにどの ``case`` にも一致しないのであれば ``default``が実行される
* ``select`` でブロックしたくないときは ``default`` を使うことができる

```go
func main() {
    tick := time.Tick(1e8)
    boom := time.After(5e8)
    for {
        select {
        case <-tick:
            fmt.Println("tick.")
        case <-boom:
            fmt.Println("BOOM!")
            return
        default:
            fmt.Println("    .")
            time.Sleep(5e7)
        }
    }
}
```