Go言語 A Tour of Go 初心者の勉強メモ

# 疑問点
* 「:=」はなんて読むんでしょうか?「コロンイコール」?「宣言代入」?

# Tutorial
* [A Tour of Go](http://go-tour-jp.appspot.com/#1) ブラウザでPlayground. 実践的でとてもわかりやすい。

# メモ
## 変数の宣言と代入

```go:page11-13.go
var a         // 変数を宣言
a = 3　　　　　 // 値を代入

var b = 1     // 変数を宣言して値を代入
c := 2　　　　　// 変数を宣言して値を代入。すでに定義済みの変数ではエラーになる

```
* :=が使えるのは関数内だけ。関数外のグローバル変数とかは必ずvarが必要。

## 定数
```go:page15.go
const Pi = 3.14
const Dio = "URYYYYYYYYYY"
```
* 定数はconst(Constants)
* 定数も変数と同じくキャメル記法

## for文

* for文の中でも := 使えます。

```go:page17.go
for i := 0; i < 10; i++ {
    fmt.Println(i*i)
}
```

* 省略もできます

```go:page18.go
    for sum := 1; sum < 1000; {
        sum += sum
    }
```


## while文

* go言語のwhile文は`for 継続条件 { 処理 }`とforを使って記述する

```go:page19.go
    sum := 1
    for sum < 1000 {
        sum += sum
    }
```

### 無限ループをfor文で表現する
* 継続条件を書かない場合は無限ループ。`for { 処理 }`とすっきり書ける

```go:page20.go
    for {
        fmt.Println("LOOOOOP!")
    }
```

## if文

* `if 継続条件 { 処理 }`　シンプル!

```go:page21.go
    if x < 0 {
        fmt.Println("Minus")
    }
```
### short statement
* short statement(一時変数?)という仕組みがあり、if文の前処理を書くことができる。
* short statementはif文の中でのみ有効。else文の中でも使える。
* この変数(short statement)がif文にだけ関連しているということを明示できる。コードの見通しが良くなってめっちゃ便利!!

```go:page23.go
    if v := a + b; sum < limit  {
        return limit  - v
    } else {
        return v - limit 
    }
```

## 構造体
* 構造体は`type Name struct { filds... }`
* 構造体名は大文字始まりでキャメル記法
* 構造体の要素も大文字始まりでキャメル記法

```go:page28.go
type Vertex struct {
    X int
    Y int
}

func main() {
    v := Vertex{1, 2}
    v.X = 4
    fmt.Println(v.X)
}
```

* 初期値がない場合はゼロ初期化(zeroedと言うらしい)が保証される
* 
```go:page28-2.go
    r = Vertex{X: 1}  // Xは1で初期化されるし、何も書いてないYはデフォルトのゼロ初期化される
    s = Vertex{}      // X:0 and Y:0
```

* 構造体の要素へはドットアクセス
* 構造体と構造体のポインタは正確には違うものだけど、そこらへんコンパイラが空気読んでくれて、ドットアクセスすると構造体でもポインタでもフィールドが返ってくる。
* つまり、構造体か構造体のポインタか意識せずにドット使っときゃOK

```go:page27-29.go
    var t1 *T = new(T)
    t2 := new(T)

    fmt.Println(t1.X)
    fmt.Println(t2.X)
```

## 配列
* 配列はSlices(スライス)と言うらしい。聞きなれない
* []T は、 T 型の配列
* 配列の長さを求めるにはlen()関数を使う

```go:page30.go
p := []int{2, 3, 5, 7, 11, 13}
fmt.Printf(p[0]) 
fmt.Printf(len(p)) 

```

### 配列の範囲指定
* 配列の範囲指定をメソッド使わずにスッキリ書ける。イイネ!

```go:page31.go
p := []int{2, 3, 5, 7, 11, 13}
fmt.Printf(p[2:4])   // index2から4まで
fmt.Printf(p[2:])    // 2以降すべて
fmt.Printf(p[:4])    // 4以前すべて
fmt.Printf(p[x:x+2]) // xから3つ
```

### 配列でfor文を回す
* `for i, obj := range array { 処理 } `
* 「forループ文のrangeフォーム」と言うらしい
* 多言語で「拡張for文」「高速列挙」とか言われてるやつ

```go:page34.go
var array = []int{1, 2, 4, 8, 16, 32, 64, 128}
for i, v := range array {
    fmt.Printf(i, v)
}
```

* iが不要な場合は、_とすると破棄される。
* 基本_にして、indexを使う時だけiにするとシンプルでGood. Swiftでも同じですね。

```go:page35.go
for _, v := range array {
    fmt.Printf(v)
}
```

## Maps (KeyValue形式)
* `make(map[keyの型]valueの型)`
* Mapsの生成にはnewではなくmake()関数を使う
* 多言語で「Map」「Dictionary」とか呼ばれてるやつ 

```go:page38.go
var stands = map[string]string {
    "ジョセフ・ジョースター" : "ハーミット・パープル",
    "トリッシュ・ウナ"      : "スパイス・ガールズ",
}
```

### Mapsの追加、参照、削除
* 要素の削除に関数を使うのはちょっと野暮ったい気もする

```go:page40.go
    var stands = make(map[string]string){} // 空のMapsを生成
    stands["仗助"]="クレイジー・ダイヤモンド"   // 要素の追加
    fmt.Println(stands["仗助"])             // 要素の参照
    delete(stands, "仗助") 　　　　　　　　　  // 要素の削除
```

### 課題
* 地味に分かりにくいけど、引数の文字列を単語で分割して、各単語の出た回数を求めてMapsで返却するというもの

```go:page41.go
func WordCount(s string) map[string]int {
	words := make(map[string]int)
	for _, word := range strings.Fields(s) {
		words[word] += 1
	}
	return words
}
```

## クロージャ
* goの関数はclosureらしい
* もちろん関数(closule)を変数に入れて受け渡しできる
* サンプルプログラムはわかりにくくて、以下のサイトのが参考になった
* [クロージャ(Closure)が難しい | 30歳からのプログラミング入門日記](http://go1ang.com/goalng-closure/)

## Switch
* switch caseは、上から下へcaseを評価する
* caseの条件が一致すれば、そこで停止してbreak。breakさせたくなければ`fallthrough`を書く
* switch文にも前処理書ける


```go:page46.go
    switch os := runtime.GOOS; os {
    case "darwin":
        fmt.Println("OS X.")
    case "linux":
        fmt.Println("Linux.")
    default:
        fmt.Printf("%s.", os)
    }
```
* 一般的に`switch 変数名 { case 変数が取りうる値: 処理 }`と書くと思うんだけど、変数名を書かなかった場合、caseには条件式が書け、caseの条件式を上から順に評価する。
* `switch {case a < 100: 処理  case b == 3: 処理}`とか。
* つまり、長い長い`if-then-else`をswitch caseで書ける…らしいんだけど、長いif-then-elseの代わりにswitch文使うのって一般的なのかな? if文とそんなに見た目も変わらない気もする。

```go:page47.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.")
    }
```

# その他
* ご指摘大歓迎です!　気になる点がありましたら気軽にコメントください。 よろしくおねがいします!