この記事は全部俺 Advent Calendar 2018の6日目の記事です。
完成形
- 開発環境をDocker化してローカル環境から切り離す
-
go fmt
やgoimports
などの各種静的解析/整形ツールをファイル保存時に自動実行するようにする- File Watchers設定ファイルをimportして各種リントを自動実行するように設定している
-
pre-commit
ファイルを設定して、golint
がエラーを出力する場合にはcommit自体できないようにする
開発環境のDocker化
Docker containerの作成
- Dockerが入っていない場合はマシンにDockerをインストールします。
- Golandを立ち上げて、
Plugins
からDocker integration
をインストールし、Golandを再起動します。 - 新規Projectを作成し、下の画像1.のように、DockerタブからDocker→imagesを選んで右クリックし、Pull Image...を選択します。
- Repositoryにgolangを入力し、OKを押すと、golang:latestのDocker Imageがプルされるはずです。
- imagesにgolang:latestが作成されるので、右クリックしてCreate containerを選択し、Create...を選びます。
- 画像2.のように、Name/Image ID/Container Nameを設定・確認し、Runを押します。
画像1. Docker Hubからgolangイメージをpullする
実行の構成を編集
Hello, World!
を表示するファイルを作成し、これをDocker環境で実行できるように実行の構成を編集します。
まず、以下の実行ファイルを作成します。
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
次に、以下の画像のように、Run Configurationsを編集します。
- Commandを
go run /go/src/golang-sample/hello.go
に変更 - Run optionsを
-v [プロジェクトルートパス]:/go/src/golang-sample
に変更
この状態でRunを実行すると、以下のようにDocker container内でHello, World!
が出力されます。
これで実行環境のDocker化は完了です。
ファイル保存時に自動でgo fmt
などの各種整形ツールを実行させる
pluginのインストール
Pluginsから、File Watchersをインストールし、Golandを再起動します。
後は、以下の整形ツールのうち、使うものについて設定してください。
【2019/09/03追記】
全部入りのファイルを以下のgistに配置しているので、こちらをローカルにファイル保存したものをimportすることでも設定完了できます。
私は上の画像のように、ファイルをimportした後、File Watchersの適用LevelをGlobalにして使用しています。こうすることで、Projectごとに以下の作業を繰り返すことなく、いつも同じLinterツールを同じように使用することができます!
go fmt/goimports
アクション検索から、File Watchers
を検索して、ToolsのFile Watchers
に移動し、+
ボタンを押してgo fmt
またはgoimoprts
を押します。
これらのツールについては以上で完了です。
golint
go get -u golang.org/x/lint/golint
でgolintをインストールし、File Watchersの設定画面で<custom>
を選択し、下記のように設定します。
goreturns
go get -u sourcegraph.com/sqs/goreturns
でgoreturnsをインストールし、File Watchersの設定画面で<custom>
を選択し、下記のように設定します。
go vet
File Watchersの設定画面で<custom>
を選択し、下記のように設定します。
実行確認してみる
以下のようなJSONファイルを読み込んで表示するGoファイルを作成してみます。
lintで自動整形されることを確認するために、わざと不要な改行を入れたり、import順番をめちゃくちゃにしたりしています。
package main
import (
"encoding/json"
"fmt"
"log"
"io/ioutil"
)
type Product struct {
Id int
Name string
Price int
}
func main() {
bytes, err := ioutil.ReadFile("vro.json")
if err != nil {
log.Fatal(err)
}
var products []Product
if err := json.Unmarshal(bytes, &products); err != nil {
log.Fatal(err)
}
for _, p := range products {
fmt.Printf("%d : %s: %d\n", p.Id, p.Name, p.Price)
}
}
このファイルについて、⌘ + Sや Ctrl + Sでファイル保存をしてみると、import順序を修正したり、不要な改行が削除され、次のようにファイルが自動整形されるはずです。
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
)
type Product struct {
Id int
Name string
Price int
}
func main() {
bytes, err := ioutil.ReadFile("vro.json")
if err != nil {
log.Fatal(err)
}
var products []Product
if err := json.Unmarshal(bytes, &products); err != nil {
log.Fatal(err)
}
for _, p := range products {
fmt.Printf("%d : %s: %d\n", p.Id, p.Name, p.Price)
}
}
地味にファイル末尾の改行も追加されたりしています。
更に、golintを適用している場合はlint結果として、以下の内容が画面下部のRunウィンドウに出力されているはずです。
/go/bin/golint /go/src/golang-sample/json_reader.go
/go/src/golang-sample/json_reader.go:10:6: exported type Product should have comment or be unexported
/go/src/golang-sample/json_reader.go:11:2: struct field Id should be ID
結果を読むと、Errorというほどでは無いが、先程のGoファイルにおいて、以下の改善点が見つかったようです。
- Productにcommentを書くべき
- Idという名前をIDという名前に変更したほうが良い
指摘されたとおりに修正を行って再度ファイル保存をすると、上記の指摘が消えることが確認できます。
pre-commitを用いてイケてないソースコードのコミットを阻止する
pre-commitとは?
.git/hooks/
以下に配置されているファイル群の1つです。
.git/hooks/
のファイル群は、何かのイベントにフックされて記載されている処理を行うものになります。
pre-commitはそのうちのcommit前に呼び出されるもので、これを編集することでcommit前にgolintを走らせ、結果がNGだった場合はコミット自体できないようにすることが可能です。
pre-commitファイル
下記のファイルを.git/hooks/pre-commit
として保存することで、git commit
を失敗する環境を作ることができます。
前提として、golintがインストールされていることが必要なのでない場合はgo get -u golang.org/x/lint/golint
しておいてください。
#!/usr/bin/env bash
failed=false
for file in "$@"; do
# redirect stderr so that violations and summaries are properly interleaved.
if ! golint -set_exit_status "$file" 2>&1
then
failed=true
fi
done
if [[ $failed == "true" ]]; then
exit 1
上記のファイルを作成した上で、先程のjson_reader.goのIDをIdに戻してコミットしようとすると、以下のような結果が出てコミットが失敗するようになります。
~/g/s/golang-sample> git commit -m "test commit"
On branch master
Changes not staged for commit:
modified: json_reader.go
上記のようなツールを使いこなして、より良い開発環境を作成していきましょう!
他に便利なツールがある場合、コメントなどでご教授いただけると幸いです!