関数とメソッド — クラスのない世界のメソッド
Rubyのdefはクラスの中に住む。Goのfuncはstructにつく。
Rubyでメソッドを作ると必ず何かのクラスの中にある。class User; def name; end; end — メソッドはクラスのもの。
Goでは関数が基本。func add(a, b int) int { return a + b } — どの型にも属さない独立関数。Rubyではこういうのをmodule_functionで作るが、Goではこれがデフォルト。
メソッド = レシーバ付き関数
Goのメソッドは「レシーバ」が付いた関数にすぎない:
type User struct { Name string }
func (u User) Greet() string { return "Hi, " + u.Name }
(u User)がレシーバ。Rubyで言えばselfが明示的に宣言されたようなもの。Rubyではdef greet; "Hi, #{name}"; endでselfは暗黙的。
多値返却
Rubyで複数の値を返すには配列でまとめる:return [value, error]。Goは文法レベルで多値返却をサポート:func divide(a, b float64) (float64, error)。これがGoのエラー処理パターンの基盤。
可変長引数
Rubyのdef sum(*numbers) → Goのfunc sum(numbers ...int) int。文法は違うが概念は同じ。ただしGoでは...が型の前に来て、Rubyでは*がパラメータの前に来る。
第一級関数
RubyにはProc、Lambda、ブロックがある。Goにも第一級関数がある — 変数に関数を代入でき、引数として渡せる。ただしRubyのブロックのように暗黙的に渡す文法はない。常に明示的。
RubyからGoへ
Ruby: class内にdef → Go: 独立func + structにレシーバでメソッド付与
Ruby: return [a, b] → Go: 多値返却が文法レベルでサポート(f64, error)
Ruby: *args → Go: ...int(可変長引数、文法が違うだけ)
Ruby: Proc/Lambda/Block → Go: 第一級関数あるがブロック文法なし
メリット
- ✓ レシーバ文法でselfが明示的 — どの型のメソッドか一目でわかる
- ✓ 多値返却でエラー処理が自然 — 例外なしでもエラー伝播可能
デメリット
- ✗ クラス継承がなく、Rubyの<継承パターンをstruct埋め込みで代替する必要がある
- ✗ ブロック/yieldパターンがなくDSLスタイルのコードを書きにくい