制御文 — if/forは似てるがwhileがない
Rubyのeach/map/selectが恋しくなるforループの世界
Rubyで配列を回す時[1,2,3].each { |n| puts n }と書く。ブロックを渡すパターンが身についている。
Goではfor _, n := range []int{1,2,3} { fmt.Println(n) }。ブロックもない、イテレータもない。forループが全て。
whileがない
Rubyのwhile condition do ... endに相当するGoコードはfor condition { ... }。キーワードはforなのにwhileのように動作する。Goはループをforひとつに統一した。
無限ループもfor { ... } — Rubyのloop do ... endに相当。
.map、.selectがない
Rubyでnumbers.map { |n| n * 2 }一行で済むものがGoでは3行:
result := make([]int, len(numbers))
for i, n := range numbers {
result[i] = n * 2
}
Goコミュニティはこれを「明示的」と呼ぶ。Ruby開発者は「冗長」と呼ぶ。どちらも正しい。
ifに括弧がない
Rubyもif条件に括弧を使わない。Goも使わない。似ている。ただしGoのifは短い宣言文を含められる:if err := doSomething(); err != nil { ... } — Rubyにないパターンだ。
switchが強力
Rubyのcase/whenはパターンマッチングが可能。Goのswitchも似ているが、fallthroughがデフォルト無効(Cと逆)。型switchもある — switch v := x.(type) { case int: ... }はRubyのcase x when Integerパターンに似ている。
RubyからGoへ
Ruby: while/until/loop → Go: forひとつで全部(whileなし)
Ruby: .each { |x| } ブロックパターン → Go: for _, x := range パターン
Ruby: .map/.selectメソッドチェーン → Go: forループ直接記述(組み込み関数なし)
Ruby: case/when → Go: switch(fallthroughデフォルト無効、型switch対応)
メリット
- ✓ forひとつに統一 — 覚えることが少ない。while、until、loopなどのバリエーションなし
- ✓ ifに短い宣言文を含められる — errハンドリングがスコープ内で綺麗に完結
デメリット
- ✗ .map/.select/.reduceがなくコレクション処理コードが3〜5倍長くなる
- ✗ Rubyのブロック/Proc/Lambdaのような第一級関数パターンがなく表現力が落ちる