for文

Go の繰り返し構文には for しかない。だけどこの for には 3 通りの使い方があって、ひとつは普通の for、ひとつは while 的なもの、そしてもひとつはいわゆる for each 的なものだ。
順番に見ていこう。

まずひとつめ、普通の for。「普通の」というのは、繰り返し用変数の初期化と繰り返し条件、変数の更新処理がある C や JavaScript なんかと同じ、くらいの意味。ただしカッコは要らない。

package main

import "fmt"

func main() {
    names := []string{ "Andy", "Bill", "Charlie" }

    for i := 0; i < 3; i++ {
        fmt.Println(names[i])
    }
}

names := []string{ "Andy", "Bill", "Charlie" } というところは、スライスっていう配列みたいなものを作ってるんだけど、これについては別の機会に書く。
実行してみよう。

^o^ > go run for.go
Andy
Bill
Charlie

ふたつめの使い方は while のようなもの。というか while そのものだ。for の後に繰り返し条件だけを書く。

package main

import "fmt"

func main() {
    names := []string{ "Andy", "Bill", "Charlie" }

    i := 0
    for i < 3 {
        fmt.Println(names[i])
        i++
    }
}
^o^ > go run for_while.go
Andy
Bill
Charlie

最後はいわゆる for each 的な使い方。range キーワードを使って、スライス(または配列)のインデックスと要素を一つずつ取り出して繰り返す。

package main

import "fmt"

func main() {
    names := []string{ "Andy", "Bill", "Charlie" }

    for idx, name := range names {
        fmt.Println(idx, name)
    }
}
^o^ > go run for_range.go
0 Andy
1 Bill
2 Charlie

ここではインデックスを idx 変数で受け取っているけど、場合によっては使わないこともある。そういう時は次のように _ (アンダースコア)で受けてやる。そうしないと idx 変数を使っていない、という警告を受けることになる。アンダースコアは、「ここに入る値は使わないよ」ということを示すものだ。

for _, name := range names {
    fmt.Println(name)
}

グローバル変数

変数を関数の外で宣言するとグローバル変数になる。グローバル変数は、同じファイル内のどの関数からでもアクセスできる。

package main

import "fmt"

var name = "Andy"

func hello() {
    fmt.Println("Hello, " + name + "!")
}

func main() {
    hello()
    fmt.Println("Good morning, " + name + ".")
}
^o^ > go run var_global.go
Hello, Andy!
Good morning, Andy.

関数の中で宣言されているのはローカル変数。ローカル変数はその関数の中だけで使える。

変数の宣言と初期化(2)

先日、変数の宣言と初期化を一緒に行うには「var 変数 = 値」という書き方をする、てなことを書いた。
これ以外に、関数の中に限っては「変数 := 値」という書き方ができる。

package main

import "fmt"

func main() {
    name := "Andy"

    fmt.Println("Hello, " + name + "!")
}
^o^ > go run var4.go
Hello, Andy!

if文

if 文はいたって普通。else ifelsif でも elif でもなく else if

package main

import "fmt"

func isZero(n int) string {
    if n > 0 {
        return "More than zero."
    } else if n < 0 {
        return "Less than zero."
    } else {
        return "Just ZERO!"
    }
}

func main() {
    fmt.Println(isZero(3))
    fmt.Println(isZero(-1))
    fmt.Println(isZero(0))
}
^o^ > go run if.go
More than zero.
Less than zero.
Just ZERO!

関数

関数の定義には func キーワードを使う。

func 関数名(引数 型...) 返り値の型 {
    処理
}

引数、返り値とも型を後に書く。珍しいな。
値を返すには return を使う。
試してみよう。

package main

import "fmt"

func hello(name string) string {
    return "Hello, " + name + "!"
}

func main() {
    fmt.Println(hello("Andy"))
}
^o^ > go run func.go
Hello, Andy!

数値型

Go にはたくさんの数値型がある。

説明
int8 8bit整数
int16 16bit整数
int32 32bit整数
int64 64bit整数
int 32bitまたは64bit整数(処理系依存)
uint8 8bit符号なし整数
byte uint8の別名
uint16 16bit符号なし整数
uint32 32bit符号なし整数
uint64 64bit符号なし整数
uint 32bitまたは64bit符号なし整数(処理系依存)
float32 32bit単精度浮動小数点数
float64 64bit倍精度浮動小数点数
complex64 float32の実数部と虚数部をもつ複素数
complex126 float64の実数部と虚数部をもつ複素数

整数は通常10進数だけど、頭に 0 をつけると8進数、0x をつけると16進数と解釈される。

型が異なると計算できない。例えば同じ整数でも int と int64 の計算をしようとすると、次のようにエラーになる。

package main

import "fmt"

func main() {
    var a int
    var b int64

    a = 10
    b = 20

    fmt.Println(a + b)
}
^o^ > go run numbers.go
# command-line-arguments
.\numbers.go:12: invalid operation: a + b (mismatched types int and int64)

こういう場合は明示的に変換しなければならない。

package main

import "fmt"

func main() {
    var a int
    var b int64

    a = 10
    b = 20

    fmt.Println(int64(a) + b)
}
^o^ > go run numbers2.go
30