Go触った所感
以前からGoは気になってたので、複数のファイル名を一括置換するrnmというCLIツールをGoで書いてみた。 自分にはあまり馴染みのない文化が結構あって良かった。
gofmtが最高
言語に直接関係ないとこだけど、gofmt
が便利!
自分は普段JSを触る事が多いが、GitHubのJSリポジトリをいくつか見るだけでもわかるように、
とにかく記述スタイルの文化が人によって違う。
だからGoがその手のコードスタイルの一切を公式で決めてくれてるのはすごく良いと思った。
インデントがタブなのはイヤだという人もいるけど、個人的にはインデントにせよクォートにせよ、
プロジェクト内で統一されてさえいれば何でもいいというスタンスなので、
リントツールの設定にいちいち気を使わずに済む方がよっぽどうれしい。
Go以降に生まれてくる全ての言語は同じように公式のフォーマッタをデフォルトで備えててほしい..!
テストの仕組み
組み込みのテスト機構はあるのにAssertionがないのはビビったけど、ちゃんとエラーメッセージを書こうという思想は理解できる。
一般的なassert.equal
みたいに失敗があったら例外を投げる方式ではなく、好きなタイミングでエラーログを吐くような感じ。
これだと途中でテストが失敗してもそこで中断されないから、「1つのテストケースにはなるべくAssersion1つ」みたいな事を考えなくて済むし、
parameterized testも普通のループで書ける。
テストファイルをテスト対象ファイルのすぐそばに置く文化はGoで初めて知った気がするけど、
両ファイルを行き来しやすいし、テストファイルを全て別ディレクトリにまとめるよりやりやすかった。
JSでももちろんできるけど、例えばテストファイルにだけ適用したいESLintのルールがあると面倒そう。
2016-08時点ではファイル名のパターンでルールを切り替える方法がないし、個々にテストディレクトリを切って.eslintrc
を置くのもダルい。
ダックタイピングなInterface
Goは静的型付言語だが、インターフェイスにちょっと特徴がある。Goではインターフェイスを明示的にimplements
する構文がなく、
struct
がインターフェイスを持つためには、そのインターフェイスが定義するメソッドを全て実装すれば良いだけ。
つまり呼び出し可能なメソッドのシグネチャによって、あるstruct
があるインターフェイスを持つかどうかが決まる。
まさしくダックタイピング。テストの時は重宝しそうだけど、逆にいうとメソッドのシグネチャでしかインターフェイスを定義できないから、
メソッドは同じだけど意味的には異なるインターフェイスを定義する、といった事はできない。
Misc
- 構文がシンプルでコレクションのライブラリも少なく、書けるコードの選択肢が限られている。それが不思議と安心感につながる。 コードの抽象化が得意な言語だと設計に腐心する楽しみがあると思うけど、Goではその手の迷いが生じづらいので、 とにかくばんばんコードを書いて形にしたい、という時に向いてるかも (でも大規模になってくるとどうなんだろう?)。
- エラーを原則例外として扱わず、ただの値として戻り値で表現するのは好み。でも呼び出し側で毎回
err != nil
をチェックするのがめんどくないとは言えない。 - 「大文字始まりかどうか」でメソッドやフィールドのスコープを定義するのはナイスアイディアだと思う。
private
とか書く手間省けるし、定義元を見なくても、使われているメソッドの名前を見るだけでスコープがわかる。 - ジェネリクスがないのは不便だけど、それが本当に必要な時はGo以外の言語を使えばいい気がする。
Goにはむしろ今のシンプルさを保って欲しい。
ただコレクションのマップやフィルタくらいはもっと簡単に書けたらいいなと思う。
for
が式になってその辺上手く解決してくれる構文があれば良いかも? - 肝心のGoroutineはまだ触れてない。。
疑問点
go get
での依存ライブラリダウンロードは安全?
Goのimport
文では、プロトコル部分を除いたURLを記述する事ができ、
go get
するとそのコードが依存しているライブラリも一緒にダウンロードするっぽい。
これが常にマスターブランチのHEADを取得するなら、開発時とgo get
時で依存関係のバージョンが変わってしまいうるのでは?
1.5で試験導入されたvendoring
を使って依存関係を管理するツールはいくつもあるが、
npm のようにバージョン管理を組み込んだパッケージ管理の仕組みを持ってるわけじゃないから、
開発時に使っていたバージョンをgo get
時にもインストールする事はできなさそう。
そのせいなのか、GitHubを見ているとvendor
以下の依存ライブラリを全部コミットしてるリポジトリを結構見かける。
main.go
の置き場所
ルートディレクトリに置いてるリポジトリもあるけど、cmd/repoName/main.go
という位置に置いてるリポジトリをよく見る。なぜ?
直感的には、main.go
がルートにいてサブディレクトリに各種コードが置かれるツリー状の構成の方がきれいそうだけど。
ルートにGoファイルを置いとけば、go test
だけでテストできるから..? (サブディレクトリを含めるにはgo test ./...
と打つ必要がある)