Edited at

[翻訳]なぜあなたはGoを学ぶべきなのか?

※この記事はKeval Patel氏の「Why should you learn Go?」を翻訳したものです。Twitterより翻訳の許可を頂きました。ありがとうございます。(Thank you!)


なぜあなたはGoを学ぶべきなのか?

1*vHUiXvBE0p0fLRwFHZuAYw.gif


“Goは将来的にサーバーの言語になる” — Tobias Lütke, Shopify


ここ数年間で、新しいプログラミング言語であるGo(GoLang)が知られるようになりました。新しい言語ほど開発者を夢中にさせるものはないですよね?。そこで私は4,5ヶ月前からGoを学び始めました。今回はなぜこの新しい言語を学ぶべきかをお伝えしようと思います。

この記事は「Hello World !!」の書き方を教えるものではありません。そのための記事は他にたくさんあります。私は現在のコンピュータハードウェアとソフトウェアについて説明しようとしているのですが、なぜGoのような新しい言語が必要なのでしょうか?。何も問題がなければ、このような解決策は必要ないはずです。


ハードウェアの限界

ムーアの法則は崩壊しています。

3.0GHzのクロック速度を持つ最初のPentium 4プロセッサは、Intelによって2004年に導入されました。今日、私のMackbook Pro 2016のクロック速度は2.9GHzです。この10年近くでプロセッサの処理能力はそれほど向上していません。下のグラフは、プロセッサの処理能力の変化を表しています。

1*Azz7YwzYYR6lDKFj8iIGZg.png

上のチャートを見て分かる通り、シングルスレッドのパフォーマンスとプロセッサの周波数は10年間安定しています。トランジスタを追加すればパフォーマンスが向上すると考えているのならば、それは間違いです。これは小規模になると(トンネリングのように)いくつかの量子特性が現れ始め、実際にはトランジスタを追加するためにより多くのコストがかかるためです。(なぜか?:What is Quantum Tunneling Limit?

そのため、上記の問題の解決策がいくつか出ました。


  • 製造業者はプロセッサにより多くのコアを追加し始めました。現在、クアッドコアやオクタコアのCPUが利用可能です。

  • ハイパースレッディングが導入されました。

  • プロセッサにキャッシュを追加してパフォーマンスを向上させました。

しかし、上記の解決策には独自の制限があります。キャッシュには物理的な制限があるため、これ以上プロセッサにキャッシュを追加することはできません。またキャッシュが大きいほどパフォーマンスは下がります。プロセッサにコアを追加してもコストがかかり、限りがあります。

これらのマルチコアプロセッサは、同時に複数のスレッドを実行することができるため、それにより並行処理が可能になります。(スレッドと並行処理については後述します。)

そのため、ハードウェアの改善に期待できない場合は、より効率的なソフトウェアを選択することが唯一の方法です。しかし残念ながら、現代のプログラミング言語はそれほど効率的ではありません。


「現代のプロセッサは、ニトロ燃料の面白い車のようなものです。彼らは、1/4マイルという点で優れています。残念なことに、現代のプログラミング言語はモンテカルロのようなもので、ひねりとターンがいっぱいです。」 -  David Ungar


※訳注:アメリカではstanding start 1/4マイル(402m)という加速性能を表す指標がある。上記では「ハードウェアは最初はめちゃめちゃ急加速できてたんだよ」という意味で使われている。またモンテカルロは、モナコ・モンテカルロという都市のことを指している。(@tenmyoさん ありがとうございます。)


Goにはゴルーチンがあります!!

上で説明したように、ハードウェアメーカーは、パフォーマンスを向上させるためにプロセッサに多くのコアを追加しています。すべてのデータセンターはこれらのプロセッサで稼働しており、今後数年間でコア数の増加が予想されます。それに加えて、今日のアプリケーションは、データベース接続やメッセージキュー、およびキャッシュの管理に複数のマイクロサービスを使用しています。そのため、私たちが開発したソフトウェアとプログラミング言語は、並行性を簡単に扱えるようにならなければならず、そしてコア数に対してスケーラブルであるべきです。

しかし、最近のほとんどのプログラミング言語(Java、Pythonなど)は、90年代から依然としてシングルスレッドのままです。それらのプログラミング言語のほとんどはマルチスレッドをサポートしています。しかし実際の問題は、同時実行やスレッドロック、競合状態、およびデッドロックにあります。 これらはマルチスレッドアプリケーションを作成することをとても難しくします。

たとえば、Javaで新しいスレッドを作成することはメモリ効率が良くありません。すべてのスレッドが約1MBのメモリヒープサイズを消費し、最終的に数千のスレッドがスケジューリングされる場合、メモリ不足によってシャットダウンを引き起こします。また2つ以上のスレッド間で通信したい場合、それは非常に困難です。

一方で、Goはマルチコアプロセッサがすでに利用可能になった2009年にリリースされました。そのため、Goは並行性を念頭に置いて開発されています。Goにはスレッドの代わりにゴルーチンがあります。それらはヒープからほぼ2KBのメモリしか消費しません。そのため、あなたはいつでも何百万というゴルーチンを回すことができます。

1*NFojvbkdRkxz0ZDbu4ysNA.jpeg

他にも利点はあります。


  • ゴルーチンは可変長なスタックを持っています。それは必要なときだけメモリを割り当てることを意味します。

  • ゴルーチンはスレッドよりも起動時間が早くなります。

  • ゴルーチンはそれら自身の間で安全に通信するための組み込みプリミティブを持っています(チャンネル)。

  • ゴルーチンを使用すると、データ構造を共有するときにミューテックスロックを使用する必要はありません。

  • ゴルーチンとOSスレッドは1:1マッピングを持っていません。また、単一のゴルーチンは複数のスレッドで実行できます。ゴルーチンは少数のOSスレッドに多重化されます。


より詳しくは、Rob Pikeの「並行性は並列性ではない」という素晴らしい解説を見てください。


上記の点から、GoはJavaやC、C++のような強力な並行処理を書くことができ、さらにErlangのように簡単に扱うことができます。

1*xbsHBQJReC5l_VO4XgNSIQ.png

Goはうまく両方の長所を備えています。簡単に効率的な並行処理を扱えます。


Goはハードウェア上で直接動作します

Java / Pythonのような他の高水準言語よりもC、C++を使用することの最も大きな利点の1つはパフォーマンスです。C / C++は、実行時にはコンパイルされており、コードを評価しません。

プロセッサはバイナリを実行できます。一般的に、プロジェクトをコンパイルするときにJavaまたは他のJVMベースの言語を使用すると、人間が読めるコードをバイトコードにコンパイルします。これは、JVMまたはOS上で実行される仮想マシンで実行できます。実行中、VMはそれらのバイトコードを解釈し、プロセッサが実行できるバイナリに変換します。

1*TVR-VLVg68KwCOLjqQmQAw.png

一方、C / C++はVM上では実行されないため、実行サイクルから1ステップが削除され、パフォーマンスが向上します。人間が読めるコードをバイナリに直接コンパイルします。

1*ii6xUkU_PchybiG8_GnOjA.png

しかし、C / C++のような言語で、変数を解放したり割り当てたりするコードを書くのは大変です。ほとんどのプログラミング言語は、オブジェクトの割り当てと削除をGarbage CollectorまたはReference Countingアルゴリズムを使用して処理します。

Goは両方の長所をもたらします。C / C++のような低レベル言語と同様に、Goはコンパイル言語です。これは、パフォーマンスが低水準言語に近いことを意味します。オブジェクトの割り当てと削除にもガベージコレクションを使用します。そのため、malloc()free()は必要ありません!。これは非常にクールです。


Goで書かれたコードは保守が簡単です

あなたに一つだけ言わせてください。Goは他の言語のような狂ったプログラミング構文を持っていません。非常にきちんとしたきれいな構文を持っています。

GoogleのGo設計者は、Goを開発するときにこの点を念頭に置いていました。Googleは非常に大規模なコードベースを持ち、何千人もの開発者が同じコードベースで作業しています。そのため、他の開発者にとってコードは理解しやすく、1つのコード領域が他のコードに与える影響は最小限である必要がありました。このきれいな構文は、コードを保守しやすく、そして修正しやすくなります。

Goは意図的に、現代のオブジェクト指向言語の多くの機能を除外しているのです。



  • クラスはありません。すべてはパッケージだけに分けられます。Goはクラスの代わりに構造体だけを持っています。


  • 継承をサポートしません。 それはコードを修正しやすくするでしょう。Java / Pythonのような他の言語では、ABCクラスがXYZクラスを継承していて、XYZクラスに何らかの変更を加えると、XYZを継承する他のクラスに何らかの副作用が生じる可能性があります。継承を削除することで、Goはコードも理解しやすくします(コードの一部を調べるために、スーパークラスを見る必要はないからです)。

  • コンストラクタはありません。

  • 注釈はありません。

  • ジェネリックはありません。

  • 例外もありません。

上記の変更により、Goは他の言語とは大きく異なり、プログラミング手法も他の言語と異なります。あなたは上記のいくつかの点が好きではないかもしれません。しかし、上記の機能がないと、アプリケーションをコーディングできないわけではありません。ほんのあと2〜3行書くだけです。そうすることで、コードがよりきれいに、より明確になります。

1*nlpYI256BR71xMBWd1nlfg.png

(コードの可読性と効率)

上のグラフは、コード構文をRuby、Python、および他の言語のように単純に保ちながら、GoがC / C++とほぼ同じくらい効率的であることを示しています。それは人間にとってもプロセッサにとっても良い状態です。

Swiftのような他の新しい言語とは異なり、Goの構文は非常に安定しています。2012年の最初のパブリックリリース1.0から変わっていません。そのため、後方互換性があります。


GoはGoogleに支えられています


  • これが直接的な技術的メリットではないことは知っています。しかし、GoはGoogleによって設計およびサポートされています。Googleは世界最大のクラウドインフラストラクチャの1つを持っており、それは大規模に広まっています。Goは、スケーラビリティと効率性をサポートするという問題を解決するためにGoogleによって設計されています。これらはあなた自身のサーバーを作成する際に直面するのと同じ問題です。

  • そのほかにも、Adobe、BBC、IBM、Intel、さらにはMediumなどの大企業でも使用されています。(出典:https://github.com/golang/go/wiki/GoUsers


結論:


  • Goは他のオブジェクト指向言語とは非常に異なりますが、それでも同じプログラミング言語です。Goがもたらすメリットには、C / C++のような高性能、Javaのような効率的な並行処理、そしてPython / Perlのような楽しさがあります。

  • もしあなたにGoを学ぶ予定がなくても、私はハードウェアの限界が効率的なコードを書くように圧力をかけていることを伝え続けます。開発者はハードウェアを理解し、それに応じてプログラムを最適化する必要があります。最適化されたソフトウェアは、安価で低速なハードウェア(IoTデバイスなど)でも実行でき、エンドユーザー体験へ全体的に良い影響をもたらします。

〜あなたがこの記事を気に入った場合は、下記の情報も見てください。 Mediumまたは私のブログをフォローすることができるので、Goの今後に関する最新情報を入手できます!~

1*8Mc_aN82rWqW56PAY5-5mg.jpeg


クレジット: