全体の感想
ある程度自分でCLIやアプリケーション開発をした上で読むと、「あれってどうやると良いんだろう?ベストプラクティス的なのって何だろう?」という疑問が解決できそうな本でした。
僕は改訂前の本をA Tour of Goを一通りやり終えた後にすすめられて読んだのですが、あまりピンときませんでした。
しかし、プログラミング言語Goを読んで文法を理解した後に自分でCLIをいくつか書いてみたり、業務でGoのマイクロサービスをいくつか開発した今読むと実感できることが増え、改めて手を動かして確認したり、実践でも活用してみたいことが多いなぁと感じました。
全体的に各テーマ類似するパッケージの特徴や使い方やベンチマークを比較しながら評価・解説されていることが多く、自分で技術選定する際の参考にもなります。
Goを活用した開発を実践する上での課題を解決する手がかりが多く見つかるよい本でした。
各章の感想
1章 Goによるチーム開発のはじめ方とコードを書く上での心得
自分の開発環境を改めて見直すきっかけになってよかったです。
パッケージ分割の基準や大きいstruct作るべきではないのはなぜかなども言語化されていてなるほどなぁと思いました。
- GOPATH、GOROOTは環境構築するたびに結局今ってどうするんやっけ?という気持ちになりますが自分の使い方では変える必要なさそうということでfix
- Build ConstraintsをBuild Constraintsと呼ぶと意識して開発してなかったのでググる力が増しました
- リポジトリ移動にpeco/peco
を使ってなかったのでmotemen/ghqと合わせて使ってみます - Makefileのhelpコマンドは人が書いたワンライナーはっつけてましたがSongmu/make2helpよさそうですね
- 「単独のパッケージとしてほかのプロジェクトから使えるかどうかがパッケージを分割する基準」よさそう
- 「正規表現のパフォーマンスが悪いのは最悪ケースの処理時間が極端に遅くならないように設計されているため」知りませんでした
- 「たくさんのフィールドを持つような巨大なstructを定義するのではなく、再利用可能な小さな部品を組み合わせてデータ構造を定義」よさそう
2章 マルチプラットフォームで動作する社内ツールのつくり方
一度でもCLIツールやアプリをクロスコンパイルして配布しようと思ったことがあるとありがたみが増す章でした。
バージョンアップデートを追うポイントについても学びがあり活かせそうです。
- マルチプラットフォームに対応したツールを作るときは特にWindows周りでパス、文字列、ファイル操作、ホームディレクトリあたりを気をつけようと思いました。自分でCLIツール作るときはとりあえずmacOSで使えるものを作った後にクロスコンパイルしてWindowsとかでも使えるようにするぞ!みたいな流れだったので、最初から気をつけるべきポイントがわかっているといざ配布するときに体験を損なわずに済みます。
- バイナリにリソースを埋め込むにあたり、jteeuwen/go-bindataやjessevdk/go-assetsはもうメンテされないので、rakyll/statikやgobuffalo/packrを勧めていた話の流れがよかったです。リソース埋め込みでまず思い浮かぶのがgo-bindataとgo-assetsだったので認識を改めることができました。
- awesome-goにGUIセクションがあることやGUI用のライブラリがたくさんあるのを知りませんでした。CLIツールを作るものという固定観念を打破してくれました。自分で積極的に作るモチベーションはないけれどそういう章があったら楽しめそうです。
- 設定ファイルのフォーマットと場所をどうするかについて各フォーマット向けライブラリの成熟度などを比較した上で筆者の見解が述べられていたり、実装の注意点が整理されていたのがとてもよかったです。cgoを使っているかどうかによるクロスコンパイルの挙動差異や、ホームディレクトリ関連でcgoに依存しないAPIが特定Goバージョンから利用できるようになったことは自分がこれまで意識できていなかった観点で、バージョンアップを追うモチベーションやポイントの1つになりました。
3章 実用的なアプリケーションを作るために
タイムアウトやシグナルハンドリングなど、実践でよく使うが理解不十分だった部分の理解が深まった章でした。
- 標準出力のバッファリングをあるLL言語と比較しつつ、bufioパッケージを利用した実装と利用していない実装を使ってシステムコール回数を
strace
で観察していたのがよかったです。システムコール自体の重みがよくわかってないのでベンチとろうと思いました。 - dustin/go-humanize便利そう。わかりやすく表示できるのも、わかりやすい形式で引数などに指定できるのもいいですね。
- 乱数系のパッケージはおそるおそる使っている感があるのでmath/randとcrypto/randの性質の違いがまとまっているのはとてもありがたかったです。
- contextパッケージはタイムアウトやgoroutineを扱う上で必ず通るのでありがたかったです。シグナルハンドリングと合わせて載っていてありがたみが増しました。シグナルハンドリング実装はよく目にしますが、シグナルを受けたときのデフォルトの挙動がドキュメント化されているのは知らず、とても良い知見でした。
- 「シグナルハンドリングでやるべき処理」
- 外部からの新規リクエストを受けなくする
- 受信時に実行中の処理が完了するまで待つ
- メモリ上に確保したバッファをすべて書き出してファイルを閉じる
4章 コマンドラインツールを作る
CLIを書くときに実践すべきことが詰まっている章でした。
はじめてCLIを開発し、テストの仕方を調べるときも筆者のブログを読ませていただいた記憶があります。
flagパッケージへの気持ちも感じることができました。
- パッケージ構成を考える上でバイナリ + ライブラリを提供するのか、ライブラリを提供するのかで変えるのは面白いなぁと思いました。ただ、バイナリメインでもコマンドはcmdの下において外部提供する意図の無いパッケージをinternal下に置くのもありなのかなぁとも思いました。何れにしても意図をパッケージ構成で伝えるというのは取り入れたいです。
- flagパッケージの使いこなしを実装を追いながら学べ、その他サードパーティの利用方法や特徴と比較していた点がとてもよかったです。章全体でなぜ?が重視されていて学びが深まったので、筆者が標準のflagパッケージしか使わなくなった点も一層気になりました。
- 「os.Exitはdefer文で呼び出した関数を実行せずに処理を終了する」あまり意識してなかった気がするので気をつけてみます。本章にも書いてあるとおりos.Exitは無闇に呼ぶべきではないと思っているので、仮に出会った時に見落としそう。
- 「ロングオプション: 説明的、シェルスクリプトやドキュメント、ショートオプション: 簡単に素早く」そうだなぁと思いました。
- 今度サブコマンドを扱うCLIを書くときはmitchellh/cliを使ってみようと思いましたがメンテされてない…?サブコマンドをインターフェースとして定義するの好きです。
5章 The Dark Arts Of Reflection
ベンチをとった解説がわかりやすく、reflectionのメリット・デメリットがよく伝わる章でした。
他の章でもベンチをとって比較するのは登場していたのですが、特に効果的に感じました。
- 型アサーションとソートについてreflectパッケージを使う場合とそうでない場合のベンチを比較していて、利用場面を選んで使うべきという主張の説得力が増していてよかったです。
- 動的にselect文を構築する部分は難しくてよくわかりませんでした。
6章 Goのテストに関するツールセット
アプリケーション開発で常に実践せざるを得ない感がもっとも強い章でした。
ベンチマークを普段ほとんどとってないので、実装方法で迷ったり、チューニングする上ではやらねばと思いました。
僕はモックはgolang/mockが好きで、比較はgoogle/go-cmpが気になるものの試せていません。
- Exampleテストのfunction名でgodocのどこに載るかが変わるのを知りませんでした。
- reflect.DeepEqualの挙動がtypeごとに説明されていてよかったです。ドキュメントにけっこう書いてあるんですね…!意外とオジェクトを比較するテストに出会っていません。
- Race Detectorの出自を知らなかったので勉強になりました。使用時にメモリ使用量5〜10倍、実行時間2〜20倍になることや、静的解析ツール出ないことも書いてあってよかったです。
- インテグレーションテストとユニットテストをBuild Constraintsで分ける話がよかったです。Makefileにテスト種別を区別して実行するためのパッケージ分類スクリプトが書いてあるのを見てきましたが、Build Constraintsを使うと明示的になりそうです。
- カバレッジについては所属組織のデフォルトMakefileやIDE、ツール(Sourcegraph)に頼っていたのでそもそものgo toolの中身を知れてよかったです。
7章 データベースの扱い方
DBやそれを扱うためのORMの章ではありますが、ライブラリ選定をちゃんとやろうという気持ちになれる章でした。
普段GoのAPIを書くことが多く、フロントも込みで開発することがないので画面込みで開発する部分は別章が丸々設けられていても楽しそうでした。(それやると別タイトルの本になりそう)
- cgoに対するpure goという概念を覚えました。
- mattn/go-nulltypeの紹介が、DB文脈でnullableを扱う上での課題を十分に説明した上で出てきて良い流れだなぁと思いました。
- ライブラリの選定プロセスを垣間見ることができる構成でとてもよかったです。
- 「本書が古くなりこれらのライブラリが古くなってしまったとしても、プログラマのみなさんがやるべきことは変わりません。新しい技術要素を調査し、あらゆる候補を比較するためにベンチマークをとることです」は最高のしめでした。