それが僕には楽しかったんです。

僕と MySQL と時々 MariaDB

PHPerがいくGolang入門 A Tour of Go Flow control statements: for, if, else, switch and defer

はじめに

Muroran Institute of Technology Advent Calendar 2018 20日目の記事です。

どうも、2018/12/20という未来から来ましたけんつです。
引き続き A Tour of Go を進めていこうと思います。

ただ昨日、気がついてしまったのですがこのあたりの構文系の解説を日本語で書くまでもないので
今回はひたすらコードで語っていこうと思います。

難解な部分だけ、適宜解説はさみます。

そして今回も全くPHP関係ないです。

For

package main;

import "fmt";

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

import "fmt";

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

    for sum < 1000 {
        sum += sum;
    }
    fmt.Println(sum);
}
||
初期化と後処理ステートメントを省略できて、こうなるとwhile文と同様の扱いとなる

* If

>|go|
package main;

import "fmt";
import "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));
}

このようにかける。
if 文より気になったのがsqrt関数の末尾でreturnしている部分、ここを return string(***);とすると
convertできない旨が帰ってきた。


続いて、評価式の前に簡単なステートメントがかけるらしいということがわかった。
ただし、そこで宣言された変数などはif~elseのスコープ内でしか使えない。

package main;

import "fmt";
import "math";


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

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

func main() {
    fmt.Println(sqrt(2), sqrt(-4));
    fmt.Println(pow(3, 2, 10), pow(3, 3, 20));
}

Switch

package main;

import "fmt";
import "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.", os);
    }

}

これも普段となんら変わらないけど、特徴としてbreakが自動的に提供されているため
明示的に記述する必要がない。

もう少し正確に書くなら、条件にマッチした部分で自動的にbreakされる。

defer

きたこれ案件。
deferは、渡した関数の実行を実行している関数が終了するまで遅延させる。

package main;

import "fmt";


func main() {
    defer fmt.Println("world");
    fmt.Println("hello,");
}

2つ以上の関数をdeferに渡すとそれはスタックされるので LIFO の順番で処理される
>|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 multi_defer.go 
done
9
8
7
6
5
4
3
2
1
0

おわりに

今回は一般的な制御構文ですごくさくっと、なにも書くことなく終わってしまったので
次回以降はもうちょい骨のあることしたい。