Go言語を学び始める人へ ~2017冬~
はじめに
この記事はAizu Advent Calendar 10日目の記事です。
最近、Go言語を最近始めた人からGo言語の周辺情報を教えて欲しいと言われました。
例えばWAFは何を使うか、ビルドするために何を使っているのか、情報を収集するのにどこを見ているのかというような情報です。
確かに新しい言語を始めるにあたってそのような情報は知っておきたいですが、意外とまとまってなかったりします。(すぐ陳腐化するからでしょうか)
なので、ここでは自分なりの周辺情報をまとめておきます。もちろん、これがすべてで必ず正しいわけではありませんので、ご了承ください。
インストール方法
Go言語では他の言語のように同じ環境に複数のバージョンをインストールするということはほとんどしません(Go言語自体の開発などを除く)。
そのため、そのままグローバルにインストールして大丈夫です。
macOS、Ubuntuでのインストール方法、そしてGOPATHの設定方法を紹介します。
macOS
$ brew install go
macOSは普通にHomebrewを使えば大丈夫です。
Ubuntu
$ apt install golang-go
このコマンドでインストールできますが、少々古いバージョンがインストールされてしまうので最新版を利用したい場合はこちらのページに従ってインストールすると良いでしょう。
例えば、Go1.9をインストールしたい場合は以下のようにします。
$ add-apt-repository ppa:gophers/archive
$ apt update
$ apt-get install golang-1.9-go
$ export PATH /usr/lib/go-1.9/bin:$PATH #PATHを通すのを忘れずに
GOPATHについて
GOPATHは1.8から `$HOME/go` がデフォルト値として設定されるようになりました。そのため特に設定しなくても問題はないです。これ以外に設定したい場合は、設定しましょう。ちなみに自分は `GOPATH=$HOME` です。
あと、 `$GOPATH/bin` をPATH通しておくことをオススメします。
`GOROOT` は設定しなくて構いません。
依存関係管理ツールについて
公式がgolang/depというツールを出しています。今から始めるのならこれを利用すれば良いでしょう。
今までは、公式で依存関係を管理できずtools/godepや
Masterminds/glideなどを使っていましたが現在は必要ありません。
https://github.com/tools/godep
https://github.com/Masterminds/glide
ちなみに、依存しているライブラリなどは `vendor/` ディレクトリに格納されます。Goは `$GOPATH` より `vendor/` を優先して見に行きます。
ちなみにGo1.5では `GO15VENDOREXPERIMENT` という環境変数に `1` を設定して、この機能有効にしていましたが今では関係ないです。
タスクランナーについて
今までMakeしか使ってきませんでした。界隈的にもMakefileを利用するのが一般的です。
Makefileはこちらの記事が参考になります。
https://qiita.com/dtan4/items/8c417b629b6b2033a541
いくつか、Goで書かれたタスクランナーもあるようですが、ほとんど利用されているところを見たことがありません。後は、Bazelなんかもあります(何かのプロジェクトで利用されていた気がしますが忘れてしまいました)。
ビルドツールについて
Goコマンドのサブコマンドである `build` を利用します。特殊なことをしていないプロジェクトであれば、 `go build` を実行すれば実行している環境向けのバイナリが同じ階層に吐き出されます。
自分はこんな感じで実行しています(実際はMakefileに `build` として定義しています)。
$ GOOS=linux GOARCH=amd64 go build -ldflags=”-w -s -X github.com/upamune/sugoi-project/config.commitHash=$(git rev-parse — verify HEAD)” -o bin/app app.go
`GOOS` , `GOARCH` を設定することでターゲットを指定してバイナリを吐き出すことができます。
https://golang.org/doc/install/source#environment
様々な環境向けに吐き出したい場合はmitchellh/goxを利用すると便利です。
https://github.com/mitchellh/gox
`ldflags` の `-X` についてですが、ビルド時に情報を埋め込むことができます。ビルド時した時の日付やコミットハッシュなどを入れる場合が多いです。
https://github.com/golang/go/wiki/GcToolchainTricks#including-build-information-in-the-executable
`ldflags` の `-s -w` はこれを指定することでシンボルテーブルを生成しないようにしてバイナリサイズを削減するためのオプションです。
UPXでさらにバイナリをサイズを削減する方法もありますが、私はやっていません。
Go周辺ツールについて
Go言語にはgofmtという最高のツールがあります。gofmtをかけるとコードのフォーマットが統一されます。公式で提供されているかつ、設定ができないというのがポイントです(従うしかないのでみんなこれに沿っている)。goimportsはgofmt+利用していないパッケージのimportの削除や逆に利用しているがimportしていないパッケージをimportに追加してくれたりします。他にも静的解析ツールの `vet` があります。ちなみに、Go1.10からは `go test` で `go vet` も走るようになるので、 `go vet` で落ちているとテストでも落るようになります。公式以外では握りつぶしているエラーを発見できるerrcheckなどがあります。そして、これらの便利なツールを合わせたgometalinterというのもあります。gometalinterには色々なlinterが含まれているので覗いてみると面白いです。
https://github.com/kisielk/errcheck
https://github.com/alecthomas/gometalinter
エディタについて
なんでも大丈夫です。
Vim, NeoVimを利用している方はfatih/vim-goを入れている方がほとんどです。
https://github.com/fatih/vim-go
IntelliJにGo Pluginを入れても良いですし、JetBrainsからはGo専用のIDE GoLandがリリースされています(旧Gogland)。
ちなみにIntelliJ+Go PluginはIntelliJ Ultimateの必要があるので有料ですし、GoLandも最近正式版がリリースされ有料となってしまいました。
VSCodeを利用して書いている人もいるようです。
テストについて
Goコマンドに `test` がサブコマンドとしてあります。
`sugoi.go` というファイルがあったとすると、テストは `sugoi_test.go` に書きます。
テストする時には、テストしたいファイルがあるディレクトリで `go test` をすれば良いです。 詳細を出力したい際には `-v` オプションを付けます。
カバレッジを取得したい際には `-cover` オプションを付けます。 `go tool cover` を利用すると `-cover` で出力されたファイルが良い感じで見ることができます。
$ go test -coverprofile=cover.out .
$ go tool cover -html=cover.out -o cover.html
複数パッケージのカバレッジを取得したい際には注意が必要でそのままそれぞれの `cover.out` を連結するだけではいけません(CodecovなどのCIサービスではそのまま連結したファイルもよしなにパースしてくれたりします)。`mode` 行を先頭だけにして、それ以降の `mode` は取り除く必要があります。
競合検知をする場合は、 `-race` オプションを利用します。
あるテストだけ実行したい場合は `-run regexp` を利用します。 `regexp` にマッチした関数だけテストが実行されます。
その他のオプションについては、こちらをご覧ください。
https://golang.org/cmd/go/#hdr-Description_of_testing_flags
テストライブラリについて
Go言語では単純に `if` で比較してダメだったらエラーを吐くというのが普通のテストの手法です。
if actual != expected {
t.Errorf(“expected: %v, but actual: %v”, expected, actual)
}
しかし、これは少々しんどいので私はstretchr/testifyを使っています。
https://github.com/stretchr/testify
assert.Equal(t, expected, actual)
このように書けば、`assert` が失敗した時は適切にエラーメッセージを出力してくれます。 `Equal` 以外にも色々あるので標準的な方法で疲れてきたらこちらを利用すると良いでしょう。
https://godoc.org/github.com/stretchr/testify/assert
あまり使っているのを見たことがないですが、私はダミーデータの生成にbluele/factory-goを利用しています。 `modeltest` というパッケージにおいて利用することが多いです。
https://github.com/bluele/factory-go
デプロイ
ビルドしたバイナリを配置してsystemdなどでデーモン化するというのを自分はやっています。Google App EngineのStandard環境はフルマネージドなのでGoの実行環境として大変おすすめですが、色々制限もあります。インフラにリソースを割けなくて、スケールさせたいならGAE/Stdがおすすめです。
ウェブアプリケーションフレームワーク
私はフルスタックフレームワークを利用せずに、標準ライブラリを元にして小さいライブラリを組み合わせて作成することが多いです。フルスタックフレームワークはrevel/revelがあります。しかし、開発は活発でなく昔のWAFというイメージがあります。
https://github.com/revel/revel
labstack/echoやgin-gonic/ginは薄いWAFとして利用されています。goaは面白いWAF(WAFというかは怪しい)です。goaのDSLを書くと、GoのコードとSwaggerが自動生成されます。これが最高なのはドキュメント(Swagger)と実装の乖離がなくなることです。
goaは少し癖はありますが、便利なのでおすすめです。Goでは様々な薄いWAFが数ヶ月おきくらいに出現してきます。その時乗り換えたかったら乗り換えることができるように、過度に依存しないよう薄くラップしておくことをおすすめします。
https://github.com/labstack/echo
https://github.com/gin-gonic/gin
https://github.com/goadesign/goa
蛇足ですが、kataras/irisは利用しない方がいいです。
https://github.com/kataras/iris
https://www.reddit.com/r/golang/comments/57w79c/why_you_really_should_stop_using_iris/
http://b.hatena.ne.jp/entry/281976155/comment/lestrrat
https://p.moznion.net/d943e3d1618bf0128bda4e27dbd4d2946ce521c0a7c586e326270614f2912934.png
https://github.com/kataras/iris/issues/219
WAFではないですが、Go言語はgRPC周辺がかなり充実しているのでgRPCを利用するのもおすすめです。最近はgRPCでサーバー書いているので近頃のWAF事情には詳しくないことに気が付きました。
DB/クエリビルダー/ORM
標準のdatabase/sqlをラップしているjmoiron/sqlxを利用しています。
https://github.com/jmoiron/sqlx
クエリビルダーはMasterminds/squirrelを利用しています。
https://github.com/Masterminds/squirrel
ORM *的* なものも一応あります。
jinzhu/gormやgo-gorp/gorp、go-xorm/xormなどが有名どころでしょうか。
https://github.com/jinzhu/gorm
https://github.com/go-gorp/gorp
https://github.com/go-xorm/xorm
最近見たvolatiletech/sqlboilerも良さそうです。
https://github.com/volatiletech/sqlboiler
自分がORMを普段利用しないのでフワッとして紹介になってしまいました。
マイグレーション
以前まではliamstask/gooseを利用していました。
https://bitbucket.org/liamstask/goose
git-schemalexを経て、gooseと似たようなmigrateに落ち着いています。migrateはgooseに比べて対応DBが多いこととや、 *GitHub* で開発されているため気に入っています。
https://github.com/schemalex/git-schemalex
https://github.com/mattes/migrate
ロガー
標準ライブラリにもログパッケージはありますが貧弱です。何かしらロギングのライブラリを入れているか、標準logをラップしたものを定義しています。
ライブラリを利用する際、以前まではsirupsen/logrusを利用していましたが、最近ではuber-go/zapを利用しています。zapはUberが開発した他のロガーよりパフォーマンスに優れ
ていることで有名なライブラリです。他に速いロガーとしてrs/zerologがあります。
https://github.com/sirupsen/logrus
https://github.com/uber-go/zap
設定まわり
自分は普段kelseyhightower/envconfigばかりを利用しています。envconfigに関しては以前記事を書いたのでそちらを参照してください。
https://github.com/kelseyhightower/envconfig
http://upamune.hatenablog.com/entry/2016/12/05/212013
後は、spf13/viperでしょうか。ファイル(JSON、YAML、TOML, HCL)、環境変数、フラグなど色々なところから設定を読むことができます。
https://github.com/spf13/viper
ちなみに、Go言語では設定ファイルとしてあまり他の言語では見ないTOMLという形式を利用することがあります。
https://github.com/BurntSushi/toml
書籍
あまり書籍の数は出ていませんが、良書が揃っています(アフィリエイトリンクではないので安心して買ってくださいw)。
プログラミング言語Go
言語自体の機能や文法を知りたい場合はこの本がおすすめです。後から読んでも学ぶことがあります。手元に置いておくと良いでしょう。練習問題が難しいのもあるので、全部無理に解く必要はありません。
https://www.amazon.co.jp/dp/4621300253
みんなのGo言語
日本の著名なGo言語を利用している方々が書いた本。実践的で入門書の次くらいに読むとちょうど良さそうです。
https://www.amazon.co.jp/dp/477418392X
スライド
自分が参考になったスライドを書いていきます(参考になったスライドはたくさんあるのですがパッと思いつくのがほとんどないので思い付きしだい追記するかもです)。
lestrratさんによるYAPCでの発表です。Perl Monger関係なく他の言語を書いていてGoを始める人におすすめの資料です。
Go関連Webサイト
golang.jpは更新されていなくて最早害悪ですが、検索すると上位に出てきてしまうのでドメインブロックして検索結果から排除しておきましょう。
こういうこともあったのでどうなんでしょうね
https://groups.google.com/forum/m/#!msg/golang-nuts/XoOhzUClDPs/jgSWxng7CAAJ
https://astaxie.gitbooks.io/build-web-application-with-golang/content/ja/index.html
勉強会
大小様々な勉強会が行われていますが、比較的大きいのはここらへんでしょうか。
Goオールスターズは最近開催されていないようです。
おわりに
思い付いたことをつらつらと書いたので、まとまりがないですが参考になる箇所があると嬉しいです。最後にもう一度言いますが、これはあくまで自分の場合です。
もっと良い方法や間違い、聞きたいことなどがあればコメントやTwitter @upamune までよろしくお願いします。
Go言語を学び始める人へ ~2017冬~ was originally published in All YoU Need Is D* on Medium, where people are continuing the conversation by highlighting and responding to this story.