Yuri’s Tech Note

技術系アウトプット

A Tour of Go vol.3

For Continued

初期化と後処理ステートメントは省略可能。

for ; sum < 1000; {
    sum += sum
}

whileはないので繰り返し処理は全てforで記述が統一される。

if

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

ifステートメントで宣言した変数はifスコープ内のみ有効なので注意する。

Switch

Switch文ではcaseの条件が一致した時点で自動的にbreakされる。

また条件なしで記述することも可能。

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する)まで遅延させる。

使い所
func main() {
    file, err := os.Open("hoge.txt")
    if err != nil {
        fmt.Println("File open error: ", err)
        return
    }

    buf := make([]byte, 1024)
    for {
        n, err := file.Read(buf)
        if n == 0 {
            break
        }
        if err != nil {
            fmt.Println("File read error: ", err)
            return
        }
        fmt.Print(buf[:n])
    }

    file.Close()
}

上のプログラムの問題はエラーが発生した場合にファイルがCloseされないということ。
こういうところでDeferを使うケースが多いようだ。

func main() {
    file, err := os.Open("hoge.txt")
    if err != nil {
        fmt.Println("File open error: ", err)
        return
    }
    defer file.Close()   // <- ここでCloseを遅延実行する

    buf := make([]byte, 1024)
    for {
        // 省略
    }

}

例外としてos.Exitを使った場合はdeferは実行されない。