GoとRust、どちらを選ぶ? Goを選ぼう。
この記事を書いたのはずいぶん前です。その間に、いくつかの点について私の考えは変わりました。
長所と短所をよりバランスよく比較したい方には、Shuttle 🚀と共同で執筆した、GoとRustの比較記事を読むことをおすすめします。
「RustとGo、どちらを選ぶべき?」これは、私がかなり頻繁に受ける質問です。どちらの言語も同じユーザー層をめぐって競合しているように見えますし、どちらもシステムプログラミング言語のように思えます。ということは、明確な勝者がいるはずですよね?
Go:実用的、実践的、そして平易

Goは洗練された言語だとは思いません。最大の特徴は単純さ、つまり簡単さです。そもそもGoはシステムプログラミング言語ですらありません。マイクロサービスやバックエンドインフラ向けのツールを書くには非常に優れていますが、Goでカーネルやメモリアロケーターを書きたいとは思いません。
しかしGoなら、仕事を片づけられます。しかも速く。
私がこれまで使ってきた中でも、Goは特に生産性の高い言語の一つです。モットーは「現実の問題を今日解決する」です。
Rustの強力な保証には代償がある

それに比べると、Rustは難しい言語です。ある程度、生産的に使えるようになるまでに何か月もかかりました。メリットを実感するには、かなりの時間を投資する必要があります。Rustはすでに強力な言語ですが、日々さらに強くなっています。私にとっては、より安全なCというより、実用的なHaskellに近く感じられます。
誤解しないでください。私はRustが大好きですし、Rustのおかげでよりよいプログラマーになれました。学ぶ価値のある、素晴らしい言語なのは間違いありません。大きな問題は、次の大規模プロジェクトにとって本当に適切な選択なのか、ということです。
要するに、Rustを選ぶなら、通常はこの言語が提供する保証が必要なはずです。
Nullポインター、競合状態、その他あらゆる低レベルの脅威に対する安全性。- 予測可能な実行時の挙動(ゼロコスト抽象化とガベージコレクターなし)。
- ハードウェアに対する(ほぼ)完全な制御(メモリレイアウトやプロセッサーの機能)。
- 他の言語とのシームレスな相互運用。
これらの機能を必要としないなら、次のプロジェクトにRustを選ぶのは得策ではないかもしれません。こうした保証には、習熟までの時間という代償があるからです。悪い習慣を捨て、新しい概念を学ばなければなりません。使い始めたばかりの頃は、借用チェッカーと何度も格闘することになるでしょう。
ケーススタディ:試し割り法による素数判定
ある数が素数かどうかを調べたいとします。最も簡単な方法は、その数を、それより小さい自然数のどれかで割り切れるか(余りが出ないか)調べることです。どれでも割り切れなければ、素数が見つかったことになります。この方法を試し割り法と呼びます。
Golangでは次のように書けます(Rosetta Codeより)。
func IsPrime(n int) bool {
if n < 0 {
n = -n
}
switch {
case n < 2:
return false
default:
for i := 2; i < n; i++ {
if n%i == 0 {
return false
}
}
}
return true
}Rustで同じことをすると、こうなります。
pub fn is_prime(n: u64) -> bool {
match n {
0...1 => false,
_ => {
for d in 2..n {
if n % d == 0 {
return false;
}
}
true
}
}
}一見すると、どちらの解決策もかなり似ています。しかし、詳しく見るといくつか違いがあります。
- Goでは単純なswitch-case文を使います。Rustでは、はるかに強力な
match文を使います。 - Goでは単純なforループで2からnまでの数を反復します。Rustでは、範囲式(
2..n)を使います。 - Goでは
return文を2つ使いますが、Rustではreturn式を1つ使います。一般に、Rustではほとんどすべてが式であり、返り値にしたり変数に代入したりできます。式について詳しくはこちらを読んでください。
多くの分野で、RustはGolangよりも関数型の性質が強くなっています。上のコードは、Rangeに実装されているanyメソッドを使って書き直すこともできます。
fn is_prime(n: u64) -> bool {
match n {
0...1 => false,
_ => !(2..n).any(|d| n % d == 0),
}
}最初は少し異質に見えるかもしれませんが、しばらくすれば自然に使えるようになります。
もちろん、これは簡単な一例にすぎません。2つの言語についてより感覚をつかむには、Rosetta Codeのコードをいくつか読んでみることをおすすめします。
ケーススタディ:テキストファイル内の重複語を見つける
目で見ながら学ぶタイプなら、GoとRustで単純な並行プログラムを書き、両言語を比較しているこちらの動画をご覧ください。
Goで気に入っている点
- コンパイルが速い
- 実践的な問題解決アプローチ
- 一般的なDevOps作業に適した充実したエコシステム
- 必要なものが一通り揃った標準ライブラリ
- IDEのサポート
- シンプルなエラーハンドリング
- マスコット 😉
Rustで気に入っている点
- 安全性:ヌルポインターがなく、データ競合もない……
- きめ細かなシステム制御
- 驚異的な実行速度(C/C++に匹敵)
- ゼロコスト抽象化
- 素晴らしく、オープンマインドなコミュニティ
- cargoによるシンプルなパッケージ管理
- トレイトによるジェネリクスのサポート
- Cとの相互運用とFFI
結論
99%の時間は、Goで「十分」です。そして、Goでは十分でない1%に当たれば、そのことが分かるはずです。そのときはRustに目を向けてください。2つの言語は実によく補完し合うからです。実践的なRustコンサルティングに興味がある方は、私のカレンダーから日時を選んでください。どのようにお手伝いできるか、お話ししましょう。
結局のところ、RustとGoは、本当の意味では競合関係にありません。
記事をランダムに読む