Go: これまでとこれから - 2019 Edition -

この投稿は [CyberAgent Developers Advent Calendar 2019](https://adventar.org/calendars/3981) 24日目 兼 [Go2 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/go2) 25日目の記事です。

先日、社内限定で開催された [カンファレンス](https://cyberagent.ai/blog/pr/%E3%82%AB%E3%83%AB%E3%83%81%E3%83%A3%E3%83%BC/10830/) で登壇した「Go: これまでとこれから - 2019 Edition -」のスクリプトから、confidential な内容を省いてお話しします。

---

![slide 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72064/9d137524-3ae5-065c-1beb-05e476d730de.png)

元々この発表をしようと思った理由は２つあります。

![slide 3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72064/418f08ec-af2d-73b0-ed98-fa74b72b7c6d.png)

1つ目は、現在CG R&Dチームにいらっしゃる山塚さんが以前ADC[^1]で発表した内容から2年が経ち、その間にもGoに様々な変化が起きたため、アップデートが必要だと思ったから。

[^1]: このときは ADTech Developer Conference。資料は社内限定公開です。

![slide 4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72064/8b2f6149-7b47-70da-0dd6-106fb1aea291.png)

2つ目に、Goが2009年の11月にリリースされてから先月でちょうど10周年と、今が発表するのにうってつけのタイミングだと思ったからです。

![slide 5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72064/851211f4-7026-ad4d-6e7c-b4fccc0f72f5.png)

今回お話しする内容についてですが、まずはじめに、Goが実際にどこでどれだけ利用されているのか見ていきます。

次に、Goエンジニアが最近まわりに増えてきているとみなさん肌で感じていると思いますし、事実ベースで紹介しますが、私が考えるGopher増加の理由をお話ししたいと思います。

そして最後に、これからGoに加わるであろう新機能の中から、私が特に注目している機能を紹介していきます。

![slide 7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72064/e9a57443-caef-c12e-df8c-1b47aa990b59.png)

それでは社内のどんなサービスで Go の活用されているか見ていきましょう！

現在私が所属している [AI事業本部](https://cyberagent.ai/) の極AIでは、フロントエンドと予測APIを繋ぐサーバサイドの開発で使っています。他にもAI事業本部の中では CheckBacks や [CA Wise](https://www.ca-wise.co.jp/) といったサービスで使われており、インターネット広告業界はScalaを使った開発が主流でしたが、Goも使われ出してきたのかなと感じています。

またゲーム事業部では主に Java や PHP でサーバサイドの開発が行われてきたのですが、最近では [QualiArts](https://qualiarts.jp/) の新規事業や、プログラミング学習サービス [QUREO](https://qureo.jp/) のサーバサイドやバッチ処理でも使われており、ゲーム業界でも使用事例を見かけるようになってきました。

メディア事業については、すでにいたるところで利用されており、ネット上でも様々な事例が紹介されているので、どのように使われているかはそちらに譲りたいと思います！（ぜひ調べてみてください！）

![slide 8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72064/5accece8-8f96-c215-fb7a-9e1f8fb61d0f.png)

国内に目を向けてみます。これは Go の公式 Wiki に載っている情報でほんの一例ですが、実に多くの会社で利用されていることがわかります。（この一覧に載っている企業以外で Go を利用しているところをご存知の方は追記してみてね）

![slide 9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72064/5372ce97-d126-96a5-6b0b-a9120b8970f2.png)

世界規模で見ると、日本でプログラミング教育やプログラミング塾が増え異分野からソフトウェアエンジニアになる人が増えているのと同様に、世界のソフトウェアエンジニア人口はここ2年で微増しています。しかし、それにもましてGoエンジニアの数は約2倍と、ムーアさんもびっくりするくらい急増しています。

![slide 11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72064/b9e29ad1-9019-0074-1ab8-37506a2fe422.png)

ここ数年で、なぜこれほどGoエンジニアが増えてきたのでしょうか？

例えば、他の主流な言語に比べ言語仕様が小さいためシンプルで誰でも読みやすいコードが書けたり、単一のソースコードで様々なプラットフォーム向けにバイナリをはけたり、並行処理を `go` キーワードで簡単に始められたりと、いろいろ理由は考えられると思います。

しかし、これら Go の利点は Go がリリースされた初期から現在に至るまで言われ続けていることで、ここ数年で Go エンジニアが増えてきた理由にはなりません。

![slide 12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72064/84fbb050-e352-7a0e-982c-ef4205c1e696.png)

そこで私は、Go エンジニアが増えてきた理由として GC が改善されたからだと考えました。[^2]

![slide 13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72064/1275bd77-da1e-a392-df3f-2bb8ecb3245d.png)

GC とはみなさんご存知の通り Garbage Collection の略で、一般的にヒープで実現されたメモリの中から使用しなくなったオブジェクトをお掃除し、再利用できるようにする仕組みのことです。

[^2]: こう断言しちゃうとマサカリが飛んできそうですね😅<br>もちろん他にも、Goコミュニティの拡大や、公式によるパッケージ管理ツールサポートなども挙げられます。

![slide 14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72064/c114693b-a550-254f-73e9-5220ee7d0180.png)

GCの処理過程は主に marking フェイズと sweeping フェイズの2種類で構成されています。marking フェイズはヒープをルートからリーフまで辿っていき、使用しているオブジェクトがどれか把握する処理を行い、sweeping フェイズでは marking フェイズで到達できなかった（＝使われなくなった）オブジェクトを削除する処理を行います。

ここで勘の良い方は、「marking フェーズで探索し終わった領域にオブジェクトがアロケートされたり、参照が変更されたりすると、そのオブジェクトは使われているにもかかわらず sweeping フェーズで削除されるのではないのか」と思われるかも知れません。

![slide 15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72064/0ab12bfa-79db-e3f6-5096-980fd8acf5d2.png)

その問題を解決する方法として、Stop The World(STW) と呼ばれる処理を行います。

![slide 16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72064/5a5f72ad-78be-7cf6-d32e-5355bc60c456.png)

やってることは非常に単純で、 marking&sweeping フェーズ中は外部からヒープに対するあらゆる操作を禁止します。

![slide 17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72064/64cda94f-e17c-4499-603a-584a0f35ebfb.png)

しかし、この STW も万能ではなく、当たり前ですが marking&sweeping フェーズ中はメインの処理が完全にストップするため、レイテンシの増加に繋がります。この単純な GC の仕組みは go1.4 まで採用されていました。

![slide 18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72064/f3365a42-3f33-3f28-4a1f-a078edd250d8.png)

go1.5 からは GC の処理フェーズを3つに分ける Tri-Color GC と呼ばれるアルゴリズムの並行版が採用されました。[^3]

[^3]: Go の GC については [こちら](https://qiita.com/gold-kou/items/4431d3dd41606d41732b) の記事が詳しいです。

![slide 19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72064/a80dfab8-5482-35c7-2d2d-38b2ce9f42f1.png)

そんなこんなで新アルゴリズムが採用されてからは順調に GC のレイテンシが減少していきました。

![slide 20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72064/5f335a7f-9894-f0d9-ecc9-ed08395f183e.png)

この図は2017年までのデータしか載ってないですが、最近のバージョン[^4]でも着々と GC は改善されており、さらにレイテンシは縮小されているものと思われます。

[^4]: 執筆時点っでの Go の最新バージョンは go1.13.5 (released 2019/12/04) です。

![slide 22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72064/e0a8f3a5-69af-c5b8-9818-2e303a8216fd.png)

さて、最後にこれから Go に組み込まれる予定の機能の中から、私が最近注目している Contracts をご紹介します。

![slide 23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72064/4dea342d-1e72-73b9-752e-455529f5783c.png)

みなさんは普段 Go を書いているときに「型が違うだけで何でほとんど同じ関数を書かないといけないの！」と一度は思ったことがあるでしょう。

![slide 25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72064/4c5f1051-8eea-fe45-b438-8bfcd111a037.png)

他の主流な言語では Genetics によりこの問題に対応しています。ただ、演算子のオーバーロードを実装しなければならない等、 Go の言語仕様を複雑にしてしまうため、導入するかどうかの議論自体はリリース初期から行われていますが、 Generics 自体の導入は見送られています。

![slide 26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72064/3a3c6c15-f9fb-83f6-e5e2-84eb325cd756.png)

代わりに Go コミュニティでは Contracts という機能が提案されています。

![slide 27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72064/7326a2b8-1bd1-1d5e-df34-3ce3d7818660.png)

Contracts が導入されることで、今まで冗長に関数を書いていましたが、必要な型を列挙した `contract` を使うことでシンプルに記述することが可能になります。[^5]

[^5]: [proposal](https://go.googlesource.com/proposal/+/master/design/go2draft-contracts.md) なので今後仕様が変わるかも知れません。実際に、このカンファレンスの後日、日本の Go コミュニティでは proposal に書かれている Contracts の仕様に変更が加わるのではないかと議論が起きました。 ref. https://go-review.googlesource.com/c/go/+/187317