Golang チュートリアル その２

##概要
「処理が速い」「並行処理」が得意ということから、
今後大規模webサービスなどで重宝されると思いましたので、
学習していきたいと思います。

今回は、「For」や「if」といったところをみていきます。

##参考サイト
以下を実施してみました。

[Welcome to a tour of Go](https://go-tour-jp.appspot.com/list)

##環境
GoogleChrome
※ブラウザ操作だけで学習できるため、　エディタを用意する必要がありません。
※私は、ローカルにCentOS8環境を用意して、チュートリアルを行います。
※Goインストール手順です。よろしければ、ご活用ください。
[CentOS8へのGo言語インストール手順](https://qiita.com/tomotomo3/items/38e7fed248278a3295b9)

##For文

 - 書き方

forループはセミコロン ; で3つの部分に分かれている。

・初期化ステートメント: 最初のイテレーション(繰り返し)の前に初期化が実行される。
・条件式: イテレーション毎に評価される。
・後処理ステートメント: イテレーション毎の最後に実行される。
・初期化ステートメントは、短い変数宣言によく利用される。
※その変数は for ステートメントのスコープ内でのみ有効。

※他の言語、C言語やJava、JavaScriptのfor ループとは異なり、
　for ステートメントの3つの部分を括る括弧 ( ) はない。
　しかし、中括弧 { } は常に必要。

```go:for.go

package main

import "fmt"

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

//実行
go run for.go

//実行結果
45
```

 - For 続き

初期化と後処理ステートメントの記述は任意である。
※for.goファイルの中身を以下に書き換える

```go:for.go

package main

import "fmt"

func main(){
	sum := 1
	for ; sum < 10; {
		sum += sum
	}
	fmt.Println(sum)
}

//実行
go run for.go

//実行結果
16
```

 - For 続き whileの代わりにForを使う
 
セミコロン(;)も省略可能。
C言語などにある while は、Goではforだけを使う。


```go:for.go

package main

import "fmt"

func main(){
	sum := 1
        //10の後ろの;を省略している
	for sum < 10 {
		sum += sum
	}
	fmt.Println(sum)
}

//実行
go run for.go

//実行結果
16
```

 - 無限ループ
 
forのループ条件を省略すれば無限ループが可能となる。

```go:for.go

package main

import "fmt"

func main(){
	i := 1
	for{
		if i < 10 {
			i += i
		}else{
			break
		}
		fmt.Println(i)
	}
}

//実行
go run for.go

//実行結果
2
4
8
16
```

##If文

ifステートメントは、forループと同様に、
括弧 ( ) は不要で、中括弧 { } は必要。

```go:if.go

package main

import (
	"fmt"
	"math"
)

func sqrt(x float64) string{
	if x < 0 {
		return sqrt(-x) + "i"
	}
	return fmt.Sprint(math.Sqrt(x))
}

func main(){
	fmt.Println(sqrt(2), sqrt(-4))
}

//実行
go run if.go

//実行結果
1.4142135623730951 2i
```

 - If内で宣言した変数
 
上記は、elseブロック内でも使うことができる

##Switch

switchステートメントはif-elseステートメントのシーケンスを短く書く方法。

Goでは選択されたcaseだけを実行してそれに続く全てのcaseは実行されない。
これらの言語の各caseの最後に必要なbreakステートメントがGoでは自動的に提供されるため。
もう一つの重要な違いはGoのswitchのcaseは定数である必要はなく、
関係する値は整数である必要はないということ。

```go:switch.go

package main

import (
	"fmt"
	"runtime"
)

func main(){

	fmt.Print("Go runs on ")
	switch os := runtime.GOOS; os{
	
	case "darwin":
		fmt.Println("OS X.")
	case "linux":
		fmt.Println("Linux.")
	default:
		fmt.Printf("%s.\n", os)
	}
}

//実行
switch.go
```

 - 条件なしのSwitch
 
条件のないswitchは、switch true と書くことと同じに意味合いです。
このswitchの構造は、長くなりがちな"if-then-else"のつながりをシンプルに表現できます。

```go:switch-with-no-condition.go

package main

import (
	"fmt"
	"time"
)

func main(){

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

//実行
go run switch-with-no-condition.go 
```

##Defer

deferステートメントは、 defer へ渡した関数の実行を、
呼び出し元の関数の終わり(returnする)まで遅延させるもの。

deferへ渡した関数の引数は、すぐに評価されますが、
その関数自体は呼び出し元の関数がreturnするまで実行されません。

```go:defer.go

package main

import "fmt"

func main(){
	defer fmt.Println("World")
	
	fmt.Println("Hello")
}

//実行
go run defer.go

//結果
Hello
World
```

 - deferを複数使用した場合

defer へ渡した関数が複数ある場合、
その呼び出しはスタック( stack )される。
呼び出し元の関数がreturnするとき、
defer へ渡した関数は LIFO(last-in-first-out) の順番で実行される。

```go:defer-multi.go

package main

import "fmt"

func main(){
	fmt.Println("counting")
	
	for i := 0; i < 10; i++ {
		defer fmt.Println(i)
	}
	fmt.Println("done")
}

//実行
go run defer-multi.go

//結果
counting
done
9
8
7
6
5
4
3
2
1
0
```

##まとめ

今回は、「For」「If」などみていきました。
次回は、ポインタを見ていきたいと思います。