Go言語は本当に何に適していますか?

野生での9年以上の間に、GoogleのGo言語、別名Golang(2019年9月のバージョン1.13)は、アルファオタクへの好奇心から、世界で最も重要ないくつかの背後にある戦いでテストされたプログラミング言語へと進化しました。クラウド中心のプロジェクト。 

DockerやKubernetesなどのプロジェクトの開発者がGoを選んだのはなぜですか?Goの特徴は何ですか、他のプログラミング言語とどのように違うのですか、そしてどのような種類のプロジェクトを構築するのに最も適していますか?この記事では、Goの機能セット、最適な使用例、言語の省略と制限、およびGoがここからどこに向かうのかについて説明します。

Go言語は小さくてシンプルです

Go、またはよく呼ばれるGolangは、Googleの従業員(主に長年のUnixの第一人者でGoogleの著名なエンジニアであるRob Pike)によって開発されましたが、厳密に言えば「Googleプロジェクト」ではありません。むしろ、Goはコミュニティ主導のオープンソースプロジェクトとして開発されており、Goの使用方法と言語の方向性について強い意見を持つリーダーシップが主導しています。

Goは、習得が簡単で、操作が簡単で、他の開発者が読みやすいことを目的としています。特にC ++のような言語と比較した場合、Goには大きな機能セットがありません。Goは構文がCを彷彿とさせるため、長年のC開発者が比較的簡単に学ぶことができます。とは言うものの、Goの多くの機能、特にその並行性と関数型プログラミング機能は、Erlangなどの言語を思い起こさせます。

あらゆる種類のクロスプラットフォームエンタープライズアプリケーションを構築および保守するためのCに似た言語として、GoはJavaと多くの共通点があります。また、どこでも実行できるコードの迅速な開発を可能にする手段として、GoとPythonの間に類似点を描くことができますが、相違点は類似点よりはるかに大きいです。

Go言語は誰にとっても何かを持っています

Goのドキュメントでは、Goを「動的に型付けされ、解釈される言語のように感じる、高速で静的に型付けされ、コンパイルされた言語」と説明しています。大きなGoプログラムでさえ、ほんの数秒でコンパイルされます。さらに、Goは、Cスタイルのインクルードファイルとライブラリのオーバーヘッドの多くを回避します。

Goは、さまざまな方法で開発者の生活を楽にします。

  • 利便性。  Goは、多くの一般的なプログラミングニーズを満たす能力において、Pythonのようなスクリプト言語と比較されてきました。並行性やスレッドのような動作を実現する「ゴルーチン」など、この機能の一部は言語自体に組み込まれていますが、GoのhttpパッケージなどのGo標準ライブラリパッケージでは追加の機能を利用できます。 Pythonと同様に、Goはガベージコレクションを含む自動メモリ管理機能を提供します。

    Pythonなどのスクリプト言語とは異なり、Goコードは高速で実行されるネイティブバイナリにコンパイルされます。また、CやC ++とは異なり、Goは非常に高速にコンパイルされます。つまり、Goでの作業は、コンパイルされた言語よりもスクリプト言語での作業のように感じられます。さらに、Goビルドシステムは、他のコンパイル言語よりも複雑ではありません。Goプロジェクトをビルドして実行するには、いくつかの手順とわずかな簿記が必要です。

  • 速度。 Goバイナリは、Cバイナリよりも実行速度が遅くなりますが、ほとんどのアプリケーションで速度の違いはごくわずかです。Goのパフォーマンスは、ほとんどの作業でCと同じくらい優れており、一般に、開発の速度で知られている他の言語(JavaScript、Python、Rubyなど)よりもはるかに高速です。
  • 移植性。 Goツールチェーンで作成された実行可能ファイルは、デフォルトの外部依存関係なしでスタンドアロンにすることができます。Goツールチェーンは、さまざまなオペレーティングシステムとハードウェアプラットフォームで利用でき、プラットフォーム間でバイナリをコンパイルするために使用できます。
  • 相互運用性。 Goは、基盤となるシステムへのアクセスを犠牲にすることなく、上記のすべてを提供します。Goプログラムは、外部Cライブラリと通信したり、ネイティブシステムコールを実行したりできます。たとえば、Dockerでは、Goは低レベルのLinux関数、cgroup、および名前空間とインターフェイスして、コンテナーマジックを機能させます。
  • サポート。 Goツールチェーンは、Linux、MacOS、Windowsのバイナリとして、またはDockerコンテナとして無料で利用できます。Goは、Red Hat Enterprise LinuxやFedoraなどの多くの一般的なLinuxディストリビューションにデフォルトで含まれているため、これらのプラットフォームへのGoソースのデプロイがいくらか簡単になります。Goのサポートは、Microsoft Visual StudioCodeからActiveStateのKomodoIDEまで、多くのサードパーティ開発環境でも強力です。

Go言語が最も効果的な場所

すべての仕事に適した言語はありませんが、一部の言語は他の言語よりも多くの仕事に適しています。

Goは、次の種類のアプリケーションを開発するために最も輝いています。

  • 分散型ネットワークサービス。 ネットワークアプリケーションは並行性によって存続し、消滅します。Goのネイティブ並行性機能(主にゴルーチンとチャネル)は、このような作業に適しています。したがって、多くのGoプロジェクトは、ネットワーキング、分散機能、およびクラウドサービス(API、Webサーバー、Webアプリケーション用の最小限のフレームワークなど)を対象としています。
  • クラウドネイティブ開発。 Goの同時実行機能とネットワーク機能、およびその高度な移植性により、Goはクラウドネイティブアプリの構築に最適です。実際、Goは、Docker、Kubernetes、Istioなどのクラウドネイティブコンピューティングのいくつかの基盤を構築するために使用されました。
  • 既存のインフラストラクチャの代替品。 私たちがインターネットインフラストラクチャに依存しているソフトウェアの多くは、古くなり、エクスプロイトで撃ち抜かれています。Goでこのようなものを書き直すと、メモリの安全性が向上し、クロスプラットフォームの展開が容易になり、将来のメンテナンスを促進するためのクリーンなコードベースなど、多くの利点が得られます。テレポートと呼ばれる新しいSSHサーバーと新しいバージョンのネットワークタイムプロトコルがGoで記述されており、従来の対応するサーバーの代わりとして提供されています。
  • ユーティリティとスタンドアロンツール。 Goプログラムは、最小限の外部依存関係でバイナリにコンパイルされます。起動が速く、再配布用に簡単にパッケージ化できるため、ユーティリティやその他のツールの作成に最適です。

言語の制限に行く

Goの意見のある一連の機能は、賞賛と批判の両方を引き出しています。Goは、特定の機能を意図的に省略して、小さくて理解しやすいという側面で誤りを犯すように設計されています。その結果、他の言語で一般的である一部の機能は、意図的にGoでは使用できなくなります。

そのような機能の1つはジェネリックスであり、関数がさまざまなタイプの変数を受け入れることができます。Goにはジェネリックが含まれておらず、ジェネリックが言語の単純さを損なうことに基づいて、言語の管理者はジェネリックを追加することに反対しています。この制限を回避することは可能ですが、多くの開発者は、ジェネリックが何らかの方法でGoに追加されるのを見たいと思っています。Goでジェネリックスを実装するための少なくとも1つの提案が提起されましたが、何も決まっていない。

Goのもう1つの欠点は、生成されるバイナリのサイズです。 Goバイナリはデフォルトで静的にコンパイルされます。つまり、実行時に必要なものはすべてバイナリイメージに含まれます。このアプローチは、ビルドとデプロイメントのプロセスを簡素化しますが、単純な「Hello、world!」を犠牲にします。 64ビットWindowsでは約1.5MBの重さがあります。 Goチームは、リリースが続くたびに、これらのバイナリのサイズを縮小するように取り組んできました。圧縮を使用して、またはGoのデバッグ情報を削除することにより、Goバイナリを縮小することもできます。この最後のオプションは、サービスが適切に失敗した場合にデバッグ情報があると便利なクラウドまたはネットワークサービスよりも、スタンドアロンの分散アプリの方がうまく機能する可能性があります。

ガベージコレクションにはある程度の処理オーバーヘッドが必要なため、Goのさらにもう1つの宣伝されている機能である自動メモリ管理は欠点と見なすことができます。設計上、Goは手動のメモリ管理を提供していません。また、Goでのガベージコレクションは、エンタープライズアプリケーションに発生する種類のメモリ負荷をうまく処理できないと批判されています。プラス面として、Go 1.8は、メモリ管理とガベージコレクションに多くの改善をもたらし、関連するラグタイムを短縮します。もちろん、Go開発者は、C拡張機能で、またはサードパーティの手動メモリ管理ライブラリを介して手動メモリ割り当てを使用することができます。

デスクトップアプリケーションなど、Goアプリケーション用の豊富なGUIを構築することを中心としたソフトウェアの文化はまだ散在しています。

ほとんどのGoアプリケーションは、コマンドラインツールまたはネットワークサービスです。とはいえ、Goアプリケーション用の豊富なGUIを提供するために、さまざまなプロジェクトが取り組んでいます。 GTKおよびGTK3フレームワークにはバインディングがあります。別のプロジェクトは、プラットフォームネイティブのUIを提供することを目的としていますが、これらはCバインディングに依存しており、純粋なGoで記述されていません。また、Windowsユーザーはウォークを試すことができます。しかし、明確な勝者や安全な長期的な賭けはこの分野では現れておらず、クロスプラットフォームのGUIライブラリを構築するGoogleの試みなど、いくつかのプロジェクトは途中で終わっています。また、Goは設計上プラットフォームに依存しないため、これらのいずれかが標準パッケージセットの一部になる可能性はほとんどありません。

Goはネイティブのシステム機能と通信できますが、カーネルやデバイスドライバー、組み込みシステムなどの低レベルのシステムコンポーネントを作成するためには設計されていません。結局のところ、GoランタイムとGoアプリケーションのガベージコレクターは、基盤となるOSに依存しています。(その種の作業のための最先端の言語に興味のある開発者は、Rust言語を調べるかもしれません。)

言語先物に行く

Go開発の次のフェーズは、開発者ベースの要望とニーズによって推進される可能性があります。Goのマインドは、頑固な例を先導するだけでなく、このオーディエンスにより適した言語に変更します。言い換えれば、Goは、ジェネリックスのように、本来意図されていなかった機能を取得する可能性があります。

Golang開発者がこれらのものを望んでいることは明らかです。2018年のGoユーザー調査では、依存関係とパッケージ管理の向上に加えて、Goの採用を拡大する方法でジェネリック医薬品を上位3つの課題の1つに挙げました。また、ジェネリック医薬品に関するGitHubの既存の提案は、Go2.xの提案として引き続き有効です。このような変更は、Java、JavaScript、Pythonが現在最高の地位を占めているエンタープライズ開発においてGoがより中心的な位置を占めるのに役立つ可能性があります。

大きな変更がなくても、上記のSSHおよびNTPの代替として、また多言語プロジェクトの一部として、インフラストラクチャ再構築プロジェクトでのGoの使用が増えることが予想されます。 

Goツールチェーンのサードパーティ実装も急増しています。ActiveStateのActiveGoは、商用でサポートされているGo言語のエディションを提供し、LLVMプロジェクトとgccgoプロジェクトの両方が、代替ツールチェーンを介して、自由にライセンスされたGoのオープンソース実装を提供します。

最後に、Goはまったく新しい言語を開発するための基盤としても機能しましたが、この2つの例は活発な開発をやめました。一例は、Go構文を合理化し、同じ概念のいくつかを独自の方法で実装し、簡単に実行できるようにGoにトランスパイルしたHave言語でした。もう1つの廃止されたプロジェクトであるOdenは、Goのアセンブラーとツールチェーンを使用して、LispやHaskellなどの言語からさらにインスピレーションを得た新しく設計された言語をコンパイルしました。

この最後の一連のプロジェクトは、ITイノベーションが真に革命的なものになる方法の1つを示しています。人々がそれを分解して再利用すると、設計者が意図していなかった用途を見つけることができます。ハッキング可能なプロジェクトとしてのGo言語の未来はまだ始まったばかりです。しかし、主要なプログラミング言語としての将来は、確かにクラウドですでに保証されています。Goの速度とシンプルさにより、長期的に維持できるスケーラブルなインフラストラクチャの開発が容易になります。