すぐに、Go と Rust の間には明確な違いがあります。 Go は、特にゴルーチンの力を使って、無限に拡張できる Web API や小さなサービスを構築することに強く焦点を当てています。 後者は Rust でも可能ですが、開発者の経験の観点からははるかに困難です。
Rust は、大量のデータの処理や、アルゴリズムの実行など、CPU に負荷のかかる処理にうまく対応します。 これは、Go に対する Rust の最大の強みです。 このチュートリアルでは、Go と Rust を比較対照し、パフォーマンス、並行処理、メモリ管理、および全体的な開発者エクスペリエンスについて、それぞれのプログラミング言語を評価します。 また、これらの要素の概要を紹介し、一目でプロジェクトに適した言語を選択できるようにします。
Rustを使い始めたばかりであれば、この先を読む前にこの初心者向けガイドでブラッシュアップするのがよいかもしれません。
すべて把握できたら、さっそく始めましょう!
パフォーマンス
元々は Google のエンジニアによって設計された Go は、2009 年に一般に公開されました。 C++ に代わる、学習とコーディングが容易で、マルチコア CPU で実行できるように最適化された言語を提供するために作成されました。 この言語には、関数をサブプロセスとして実行できるゴルーチンがあります。
Goの大きな利点は、ゴルーチンをいかに簡単に使用できるかということです。 関数に go
構文を追加するだけで、サブプロセスとして実行されるようになります。 Go の並行処理モデルでは、複数の CPU コアにワークロードを展開することができ、非常に効率的な言語です。
package mainimport ( "fmt" "time")func f(from string) { for i := 0; i < 3; i++ { fmt.Println(from, ":", i) }}func main() { f("direct") go f("goroutine") time.Sleep(time.Second) fmt.Println("done")}
Multicore CPU サポートにもかかわらず、Rust は依然として Go よりも優れた結果を出しています。 Rust は、アルゴリズムやリソース集約的な操作の実行において、より効率的です。 Benchmarks Gameでは、2分木などのさまざまなアルゴリズムでRustとGoを比較しています。 テストしたすべてのアルゴリズムで、Rustは少なくとも30パーセント、二分木の計算の場合は最大1,000パーセント高速化しました。 Bitbucket による調査でも、Rust は C++ と同等のパフォーマンスを示す同様の結果が出ています。
(Source: Benchmarks Game)
並行処理
上述のように、Go では並行処理をサポートしています。 たとえば、API リクエストを処理する Web サーバーを実行しているとしましょう。 Go のゴルーチンを使用して、各リクエストをサブプロセスとして実行し、利用可能なすべての CPU コアにタスクをオフロードすることによって効率を最大化できます。
ゴルーチンは Go の組み込み関数の一部であり、Rust は並行処理をサポートするネイティブ async/await 構文のみを取得しています。 そのため、並行処理に関しては、開発者の経験値で Go に軍配が上がります。
Rust の簡略化されたスレッドの例です。
use std::thread;use std::time::Duration;fn main() { // 1. create a new thread for i in 1..10 { thread::spawn(|| { println!("thread: number {}!", i); thread::sleep(Duration::from_millis(100)); }); } println!("hi from the main thread!");}
同時実行は常に、開発者にとって茨の道でした。 開発者のエクスペリエンスを損なうことなく、メモリ安全な同時実行を保証するのは簡単なことではありません。 しかし、この極端なセキュリティ重視の姿勢が、証明可能な正しい同時実行の作成につながったのです。 Rust では、メモリ安全性のバグを防ぐために、リソースの未承諾アクセスを防ぐ所有権の概念を実験しました。
Rust では、一般的なメモリ安全性の落とし穴を回避するために 4 種類の並行処理パラダイムを提供しています。 チャネルとロックです。
Channel
チャネルは、あるスレッドから別のスレッドへのメッセージ転送を支援します。 この概念は Go にもありますが、Rust では、リソースの競合状態を回避するために、あるスレッドから別のスレッドにポインタを転送することができます。 ポインタを渡すことで、Rustはチャネルに対してスレッド分離を強制することができます。
Lock
Data is only accessible when the lock is held.このように、Rust は並行処理モデルに関してメモリ安全性にこだわっています。 Rust は、Java などのプログラミング言語でよく見られる cod の代わりにデータをロックするという原則に依存しています。
所有権の概念とすべての同時実行パラダイムの詳細については、「Rust による恐るべき同時実行」をチェックしてください。 Rust は、メモリ安全な並行処理を可能にするために重要な型安全性を次のレベルまで高めています。
Bitbucket ブログによると、「Rust の非常に厳しく衒学的なコンパイラーは、使用するすべての変数と参照するすべてのメモリ アドレスをチェックします」。 これは、Rust がメモリ安全性に極端にこだわるため、バッファオーバーフローやレースコンディションに陥らないことを意味します。 しかし、これにはデメリットもあります。 例えば、コードを書きながら、メモリ割り当ての原則を過剰に意識する必要があります。
開発者の経験
まず最初に、各言語に関連する学習曲線について見てみましょう。 Go はシンプルであることを念頭に置いて設計されています。 開発者はしばしば「退屈な」言語と呼びますが、これはつまり、組み込み機能の限られたセットにより、Go を簡単に採用できるということです。
さらに、Go は C++ に代わるより簡単な選択肢を提供し、メモリ安全性やメモリ割り当てなどの側面を隠します。 Rust は別のアプローチで、メモリ安全性などの概念について考えさせます。 所有権の概念とポインタを渡す機能により、Rust は学習するのにあまり魅力的な選択肢ではありません。 メモリ安全性について常に考えていると、生産性が低下し、コードがより複雑になるに違いありません。
Rust の学習曲線は、Go と比較してかなり急です。 しかし、Go は Python や JavaScript のようなより動的な言語よりも学習曲線が急であることは言及に値します。
When to use Go
Go は幅広い使用ケースでうまく機能するので、Web API を作成するのに Node.js に代わる素晴らしい選択肢となります。 Loris Cro が指摘するように、「Go の並行処理モデルは、複数の独立したリクエストを処理しなければならないサーバー側アプリケーションに適している」のです。 これはまさに、Go がゴルーチンを提供する理由です。
さらに、Go には HTTP ウェブ プロトコルのサポートが組み込まれています。 組み込みの HTTP サポートを使用して小さな API をすばやく設計し、それをマイクロサービスとして実行することができます。 したがって、Go はマイクロサービス アーキテクチャによく適合し、API 開発者のニーズに応えます。
要するに、Go は、開発速度を重視し、パフォーマンスよりも構文の単純さを好む場合によく適合しています。 その上、Go はコードの可読性に優れており、これは大規模な開発チームにとって重要な基準です。
Go を選択する場合:
- シンプルさと読みやすさを重視する場合
- コードをすばやく書くための簡単な構文が欲しい場合
- Web 開発をサポートするより柔軟な言語を使用したい場合
Rust を使う場合
大量のデータを処理するなどパフォーマンスが重要な場合 Rust は素晴らしい選択肢となります。 さらに、Rust はスレッドの動作やスレッド間でリソースを共有する方法を細かく制御できます。
一方で、Rust は学習曲線が急で、メモリ安全性の複雑さが増すため開発速度が遅くなります。 これは必ずしも欠点ではなく、Rust はコンパイラがすべてのデータポインタをチェックするため、メモリ安全性のバグに遭遇しないことを保証しています。
Choose Rust when:
- You care about performance
- You want fine-grained control over threads
- You value memory safety over simplicity
Go vs. Rust.Rust は、Rust を選択することになります。 率直な感想
まず、類似点を強調することから始めましょう。 Go と Rust はどちらもオープン ソースであり、マイクロサービス アーキテクチャと並列コンピューティング環境をサポートするように設計されています。
しかし、結局のところ、どの言語がベストなのでしょうか?
この質問にアプローチする方法はたくさんあります。 私は、どのような種類のアプリケーションを構築したいのかを考えることをお勧めします。 Goは、マイクロサービスアーキテクチャをサポートしながら、組み込みの並行処理機能を活用したWebアプリケーションやAPIの作成に適しています。
また、Rustを使ってWeb APIを開発することもできますが、この使用例を念頭に置いて設計されていません。 Rust はメモリ安全性に重点を置いているため、特にかなり単純な Web API の場合、複雑さと開発時間が増えます。
できるだけ簡単に言うと、Go 対 Rust の議論は、実際にはシンプルさ対セキュリティの問題です。 生産 Rust アプリケーションの完全な可視化 Rust アプリケーションのデバッグは、特にユーザーが再現困難な問題を経験する場合、困難なことがあります。 Rust アプリケーションのパフォーマンスの監視と追跡、エラーの自動表面化、遅いネットワーク要求とロード時間の追跡に興味がある場合は、LogRocket を試してみてください。
LogRocket は Web アプリの DVR のようなもので、Rust アプリで発生する文字通りすべてのことを記録します。 問題が発生した理由を推測するのではなく、問題が発生したときにアプリケーションがどのような状態であったかを集計し、報告することができます。 LogRocket はまた、アプリのパフォーマンスを監視し、クライアント CPU 負荷、クライアント メモリ使用量などのメトリックを報告します。