112
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

Goは本当に1980年代の言語みたいなのか。

はじめに

2020年8月15日現在、golang.orgのトップページに、The Why of Goという動画が、Featured Videoとして紹介されています。

Goに初めて触れて、ちょうどなぜこうなっている?と思う機会が多かったので、自分なりにまとめてみようと思います。
注: 要約というよりは、気になる部分をピックアップして解釈して文字にしているものなので、総合的な内容は動画を見てください。

Goとは1980年代の言語なのか

Goとは1980年代の言語のようだと批判される。糖衣構文、多態、Genericsが使えない、依存性管理が粗末等と批判する人にとってGoは、1980年代以降のプログラミング言語の進化の歴史を無視しているように見えるようだ。

だけど、それらの要素があったら21世紀のプログラミング言語といえるということなのだろうか?
このプレゼンテーションでは、そういう疑問をきっかけにGoのなぜ(The Why of Go)を考える。

Goはどういう経緯で作られた?

GoはGoogleでのソフトウェア開発のなかで見つかった課題に対する答えとして作られた。
具体的にはC++, Java, Pythonなどの言語では、マルチコアCPU、ネットワーク上で動作するシステム、大きなクラスターで動作させるプログラムといったここ最近のソフトウェア開発で起こった変化に対して、どちらかといえば対処療法の繰り返しが続いていて、これらの特徴に合わせて組み換えは行われていなかった。
さらにそれに加えて、ここ最近のプロジェクトでは何百万行ものコードを何千人ものプログラマが作り上げ、さらに毎日それが更新される時代になった。それにともないビルドの時間も、巨大なコンパイラクラスターでも数時間かかるようなレべルになっていた。
これらの問題に対する答えとして作られたのがGo。

Goの21世紀的特徴

Concurrency / 並列平行処理

GoではGreen Thread(OSのスレッドではなく、ユーザーレベルのスレッド。)が主要な言語機能の1つとして実装されている。
C10K問題、Nonblocking I/O、kqueue、epoll、java.nioといったキーワードが登場する歴史の中で、並列平行処理をEventで実現するやり方(nodejs等)とThreadで解決するやり方(java.nio等)があり、それぞれ長所短所があるが、Goのgo routine(前述のGreen ThreadのGoでの呼び方)が良いところどりであるということ。
//TODO いかに良いところどりなのかが読み取り切れていない。 → コメントに @ktz_alias さんの解説あり。

Distributed Systems / 分散システム

Goはなにかruntimeがあらかじめインストールされている必要がなく、即実行可能なバイナリを作れる。
これが、高度に分散されたシステムにおいていろいろな処理や手続きをシンプルにしてくれる。

Garbage Collection / GC

GoのGarbage Collectionの特徴はtail latency(まれに発生する最悪ケース)を最小限にしようとしていること。
JavaならたとえばStop The Worldが発生するとそこでのパフォーマンスはtail latencyを記録するだろう。
モニターしても見つかりにくく、予測しにくいTail Latencyは、ダイレクトに無駄につながる。

Memory Locality / 参照の局所性

(GCの話題から続く部分があるが)
参照の局所性はJavaが生まれたころより今日ずっと重要になっている。
JavaのGCは長い時間をかけて最適化されてきたが、基本的に組み込み型以外の値型がなく、GCするときには参照を追いかける必要がある。また、最適化されているといっても、FullのGCはStopTheWorldである。
一方Goでは、structや真の値型(値型っぽいけどそうではないものと対比して)を持ち、無駄がなく、コレクションのLazyな初期化といった機能もある。また、GoのGCはアプリケーションをBlockせずに動かせる。

Javaでは複数の値を返すことができないのでWrapすることになりそれもGCのプレッシャーになる。
組み込み以外の値型がないことはキャッシュの面でも不利がある(Java10のMajorFeatureとして頑張ってるのもこのため)

要するに、Goは必要な時にメモリを効率的に扱うためのツールが揃っていて、かつフレキシブルである(上記の、「必要な時に」いう意味でもあり、C++やRustのように全部入りor何もなしという構図ではないという意味でもある)

Readability

"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." - Kernighan’s law
デバッグというのはコードを書くのに比べて2倍は難易度が高いものである。これに基づけば、あなたが自身の最高の実力をもってコードを書いたとき、あなたはそれをデバッグできないということだ。

大きな組織では常に経験が不十分なプログラマを雇わないといけない時もある。
小さな会社だったGoogleも、2017年時点でエンジニアは6万人いることになる。
何万人もの開発者が、毎週何万行ものコードを増やしながらソフトウェア開発をするときに、多態やメタClass(インスタンスがクラスになるもの)を使ったコードを現実的な精度で扱えるの?

"This is an insult to intelligent programmers (知性あるプログラマに対する冒涜だ)"という人もいるが、そもそもソフトウェア開発者というのはプログラムを書いたり、他人のプログラムを直したりすることこそが仕事なのではなく、ビジネス上の問題を解決することが仕事なのである。
あなたが書いたプログラムを他の人間がメンテナンスできないということは、まあ、首にはならないかもしれないが、昇進できないということでもある。10年あれば1人の開発者が5社をめぐる時代なんだ。読みやすさやシンプルさは重要だよ。

馬車と歩きの時代から車の時代になった時に、政府が様々なルールを作った。個人の自由だと言って、車道の右側(動画内では左側)を走ったら何が起こるだろうか。
Goはアカデミックな研究のために作られたのではなく、今の時代に合わせたエンジニアリングのために作られたものだ。
今はみんなが車を持ち始めたときのように、新たなものの作り方がされる時代だ。交通ルールにあたるものが必要だ。

“Simplicity is a great virtue but it requires hard work to achieve it and education to appreciate it. And to make matters worse: complexity sells better.” ― Edsger Wybe Dijkstra
シンプルさというのはすばらしいものだが、組み立てるのは大変で、きちんと教育をうけないと良さを理解できない。しかも、得てして複雑なものの方が金が儲かるというのがなおさら事を難しくする。

感想

Goを少しだけ触って感じた疑問が、生まれた歴史や意図を聞くことで興味にかわった。
しっかり触ってもう一度反芻したい。
また、並行処理をThreadで解決するやり方と、Eventで解決するやり方、その良いとこどりというGoのGreen Threadという部分は、わかった気になっている領域を含むので別記事でまとめたい。
※ コメントに @ktz_alias さんの解説あり。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
112
Help us understand the problem. What are the problem?