golangを基礎から学ぶ　制御構造編



## 制御構造
いくつかの制御構造、いわゆる、if、 while、for、 foreach、switch　などについて。

### if
条件部、丸括弧不要。
本件部、波括弧必要。

```go
x := 3
    
if x > 0 {
	fmt.Println(x)
}
```

初期化ステートメントを記述できるため、そこでローカル変数の準備を行うのが一般的。

```go
if err := file.Chmod(0664); err != nil {
    log.Stderr(err)
    return err
}
```

少し複雑な条件1
丸括弧使っていけないわけではない

```go
x := 3
y := 4
if (x > 0 && y > 5) || (x > 0 && y > 0)  {
	fmt.Println(y)
}
```

少し複雑な条件2
`elseif`  →　×
`else if` →　○

```go
x := 3
y := 4
if (x > 0 && y > 5) || (x > 0 && y > 8)  {
	fmt.Println(y)
} else if  x == 2 || y == 4 {
    fmt.Println("elseif")
} else {
    fmt.Println("else")
}
```



数値 0 の真(true)偽(false)をifで確かめたところ処理はエラーになった↓
`non-bool 0 (type untyped number) used as if condition`
go言語は真偽値の型をもっていて条件式はその型でなければいかんということで、0は整数型であって、真偽型ではないから以下の処理はコンパイルエラーになる。

```go
if 0 {
    fmt.Println("true")
} else {
	fmt.Println("false")
}
```


### for, while(golangにはない)
ループにはdoやwhileはなく、若干改良されたforループだけがある

whileに相当する形式

```go
x := 100
for x > 0 { 
	x--
	fmt.Println("Value of i is now:", x)
}
```


`for ;; {...}`
の書き方はいわゆる無限ループなので、条件を適切に扱う必要がある
do while やろうとするとこんな感じになる↓

```go
for value := 0;; {
	value++
    fmt.Println(value)
    if value % 6 == 0 {
    	break
    }
}
```

典型的なfor

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

foreach 的な1

```go
items := map[int]int{0:10 , 1:20}
for key, value := range items {
    fmt.Println("key:", key, " value:", value)
}
```

foreach 的な2
連想配列で

```go
commits := map[string]int{
    "rsc": 3711,
    "r":   2138,
    "gri": 1908,
    "adg": 912,
}
for key, value := range commits {
    fmt.Println("key:", key, " value:", value)
}
```

### switch
golangのswitchは多機能

ごく普通のswitch
数値型のものを引数にしてるなかで、他の型がcaseに指定するコンパイルエラーになる

```go
i := 5
switch i {
case 4: fmt.Println("number 4")
case 5:fmt.Println("number 5")
case 6: fmt.Println("number 6")
//case i>7: fmt.Println("is > 7") //compile error as type int and bool don't match between case and switch
default: fmt.Println("default")
}
```

こちらは文字列ほ引数にしたswitch

```go
s1 := "abcd"
s2 := "efgh"
switch s1 { 
case s2: fmt.Println("the two strings are equal")
default: fmt.Println("the two strings are NOT equal")  //since nothing else matches, the default block is executed
}
```

一つのcaseに複数の値を指定することもできる

```go
j := 4
switch j {
case 1,3,5,7,9: fmt.Println(j, "is odd")
case 0,2,4,6,8: fmt.Println(j, "is even")
default: fmt.Println(j, "is not an integer between 0 and 9")
}
```

switch-caseのデフォルト動作はfallthroughではない
つまり、breakを書かなくても途中でcaseマッチしたら終了するということ
fallthroughステートメントを使うと、式switch(§式switch)の次のcase節の先頭のステートメントへ制御をうつす（この場合caseの条件はみない）

```go
k := 6
switch k {
case 4: fmt.Println("was <= 4"); fallthrough;
case 5: fmt.Println("was <= 5"); fallthrough;
case 6: fmt.Println("was <= 6"); fallthrough;
case 7: fmt.Println("was <= 7"); fallthrough;
case 8: fmt.Println("was <= 8"); fallthrough;
default: fmt.Println("default case") 
}
```
output

```
was <= 6
was <= 7
was <= 8
default case
```


if-elseチェーン的に書ける

```go
num := 15
switch {
case num == 1:
	fmt.Println(1)   
case (num > 5 && num < 11) && (num > 5 && num < 16):
	fmt.Println(2)   
case (num > 5 && num < 11) || (num > 5 && num < 16):
	fmt.Println(3)
default:
    fmt.Println("default")
}
```






## 参考

[The Go Programming Language](http://golang.org/doc/)
[Tour Go](http://tour.golang.org/)