公式の A Tour of Go ではじめて Go 言語を触ってみました。
以下、フロー制御(for, if, switch, defer)について学んだことのメモ。
前回の記事はこちら
for
- 初期化ステートメント: 最初のイテレーションの前に初期化が実行される
- 条件式: イテレーションごとに評価される
- 条件式の評価が false となった場合にイテレーションを停止
- 後処理ステートメント: イテレーションごとの最後に実行される
package main
import "fmt"
func main() {
sum := 0
for i := 0; i < 10; i++ {
sum += i
}
fmt.Println(sum) // 0 + 1 + ... + 9 = 45
}
- 初期化ステートメントと後処理ステートメントは任意
package main
import "fmt"
func main() {
sum := 1
for sum <= 4 {
sum += sum
}
fmt.Println(sum) // 1 + 1 + 2 + 4 = 8
}
if
- 括弧は不要
- if のスコープ内だけで有効な変数を宣言できる
package main
import (
"fmt"
"math"
)
func pow(x, n, lim float64) float64 {
if v := math.Pow(x, n); v < lim {
// v は if のスコープ内でのみ有効
return v
} else {
// v は else の中でも使える
fmt.Printf("%g >= %g\n", v, lim)
return lim
}
}
func main() {
fmt.Println(
pow(3, 2, 10), // 9 < 10 なので return v
pow(3, 3, 20), // 27 < 20 ではないので return lim
)
}
switch
- if-else ステートメントのシーケンスを短く書く方法
- break 不要
- case が定数や整数値である必要はない
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.\n", os)
}
}
- 条件のない switch は
switch true
と同義 - 長くなりがちな if-then-else のつながりをシンプルに表現できる
package main
import (
"fmt"
"time"
)
func main() {
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.")
}
}
defer
- deferへ渡した関数の実行を、呼び出し元の関数のreturnが完了するまで遅延させる
- deferへ渡した関数の引数はすぐに評価されるが、実行は呼び出し元のreturnが終わるまでお預け
package main
import "fmt"
func main() {
defer fmt.Println("world")
fmt.Println("hello")
}
- deferへ渡した関数が複数ある場合、その呼び出しは stack される
- LIFO (last-in-first-out) の順番で実行される
package main
import "fmt"
func main() {
fmt.Println("counting")
for i := 0; i < 10; i++ {
defer fmt.Println(i)
}
fmt.Println("done")
}
// 9, 8, ..., 1, 0
次回