Edited at

A Tour of Go memo basics_2 (制御文)

More than 1 year has passed since last update.


目次

basics_1 (パッケージ, 変数, 関数)

basics_2 (制御文)

basics_3 (構造体/配列/map/slices)


制御文

制御文といえば何を思い浮かべますか?

今回ここでまとめるのはforif/else/elseif、またseitchdeferといった制御文についてやっていこうと思っています。


for

GoでForループを書く際はセミコロンで3つの区域に分けます。


sample.go

//~~~前略~~~

func main () {
sum := 0 //型推論でint
for i := 0; i < 10; i++ {
sum += i
}
fmt.println(sum)
}

この書き方に少し違和感はありますがPHPやJavaScriptの()なしと考えればいいかなと考えました。

このFor構文はいつもの初期値;条件;増加値となります。


For continued (forのWhile化)

実はGoの初期化と後処理は任意記述であり下記のような記述をすることによってForのWhile化ができます。


sample.go

//~~~前略~~~

func main () {
sum := 1
for ; sum < 1000; {//なんだったら ; もいらない
sum += sum
fmt.Println(sum)
}
}

Goのforでは内部の条件を抜いた場合無限ループ扱いとなります。


if

If文についてですが、For同様に内部の条件には()が必要なく記述することができます。

例えば


sample.go

package main 

import "fmt"

func strCompName (name1, name2 string) bool {
if name1 == name2 {
return true
}
return false
}

func main () {
if strCompName ("hoge","huga") {
fmt.Println("一致しとるで")
} else {
fmt.Println("一致しとらんで")
}
}



If with a short statement (if内での宣言)

IF内でstatementを記述することができこれはIF内のみでのスコープ変数として扱われます。


sample.go

//累乗計算

package main

import (
"fmt"
"math"
)

func pow(x, n, lim float64) float64 {
if v := math.Pow(x, n); v < lim {
return v
}
return lim
}

func main() {
fmt.Println(
pow(3, 2, 10),
pow(3, 3, 30),
)
}


ここではshort statementのみではなくIfの複数条件も例として挙げている。


Switch

ifをさらに短くするためにGoでは存在します。

私の知っているPHPやJavaSprictなどとは違いGoではcaseで一致しても停止した後に後続のcaseを行うのではなく自動的にbreakを行います。


sample.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:
// freebsd, openbsd,
// plan9, windows...
fmt.Printf("%s.", os)
}
}


ついでにSwitchの条件は省いてcase文に内包できます。


Defer(後処理)

関数の最後の処理として実行できる遅延処理。

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


sample.go

package main

import "fmt"

func main() {
defer fmt.Println("1")
defer fmt.Println("2")

fmt.Println("3")
}


結果

3

2
1

なぜこのようになるかといいますと、defersはLIFOつまるところのStackで保存され関数のreturn時に呼び戻されるのです。