エンジニアはこわくない

自分の好きな音楽とか雑記とかエンジニアっぽい内容を好きなように書く場所。

go vetコマンドをドンドン使っていこう

f:id:tsujitaku50:20170107113922p:plain:w300

今日はgo vetコマンドについての知見を手に入れたので、それについて書こうと思います。
goコマンドには様々な種類があります。

% go --help
Go is a tool for managing Go source code.

Usage:

    go command [arguments]

The commands are:

    build       compile packages and dependencies
    clean       remove object files
    doc         show documentation for package or symbol
    env         print Go environment information
    fix         run go tool fix on packages
    fmt         run gofmt on package sources
    generate    generate Go files by processing source
    get         download and install packages and dependencies
    install     compile and install packages and dependencies
    list        list packages
    run         compile and run Go program
    test        test packages
    tool        run specified go tool
    version     print Go version
    vet         run go tool vet on packages

Use "go help [command]" for more information about a command.

Additional help topics:

    c           calling between Go and C
    buildmode   description of build modes
    filetype    file types
    gopath      GOPATH environment variable
    environment environment variables
    importpath  import path syntax
    packages    description of package lists
    testflag    description of testing flags
    testfunc    description of testing functions

Use "go help [topic]" for more information about that topic.

コマンドで調べた結果上記のgoコマンドが存在するようです。
僕が良く使うのはrun,version,get,buildあたりなのですが、たまたま先輩から教えてもらった
go vetについて少し書きたいと思います。

go vetコマンドって何?


そもそもこのコマンドって何をしてくれるコマンドかさっぱり分かりませんでした。
ということで公式ドキュメントを見に行きました。

以下は公式ドキュメントから

vetコマンドはGoのソースコードをチェックし、Printfの呼び出しで引数が書式文字列(format string)で列んでないような欠陥をレポートします。 vetはヒューリスティック(heuristic)な問題を扱い、すべてのレポートが本当に問題であることを保証しません。しかし、コンパイラで見つけられないエラーを検出することができます。

コマンドの終了ステータス(exit code)は、コマンドの起動を間違うと"2"、問題がレポートされると"1"、"0"はそれ以外です。 コマンドは起こりうるすべての問題をチェックできず、信頼性の低いヒューリスティックに依存することを覚えておいてください。 ですから、ガイダンスとしてだけ使用すべきで、確固としたプログラムの正当性の指標として利用すべきではありません。

僕の解釈になりますが、
コンパイラで見つけられないエラーを検出することができるよ。ただ検出してもそのコードが本当に問題であることを保証できないよ。なので、エラーが検出されたら一応調べる程度はしてね。」
という具合のものかなと思っています。

使い方


  • 1つのファイルを調べる場合

    go tool vet xxx.go

  • ディレクトリの中になる全てのgoファイルを調べる場合

    go tool vet ディレクトリ

参考例


1つgo vetの例を出しておきます。
そもそも先輩から指摘されたのが「go vetしたらstructのところでエラーが出てるよ」という指摘でした。 なので実際にgo vetしてみました

% go tool vet go-connpass-cli/src/
xxx: struct field tag `json:results_returned` not compatible with reflect.StructTag.Get: bad syntax for struct tag value
xxx: struct field tag `json:results_available` not compatible with reflect.StructTag.Get: bad syntax for struct tag value
xxx: struct field tag `json:results_start` not compatible with reflect.StructTag.Get: bad syntax for struct tag value
・・・

上記のエラーがずらっと検出されました。
これはstructにjsonアノテーションを付けていたのですが、そのアノテーションがおかしいのが原因で検出されたようです。
以下に実際のコードと修正版のコードを記載します。

実際にエラーが検出されたstruct

type Connpass struct {
    ResultsReturned  int `json:results_returned`
    ResultsAvailable int `json:results_available`
    ResultsStart     int `json:results_start`
    Events           []Event `json:events`
}

修正してエラーが検出されなくなったstruct

type Connpass struct {
    ResultsReturned  int `json:"results_returned"`
    ResultsAvailable int `json:"results_available"`
    ResultsStart     int `json:"results_start"`
    Events           []Event `json:"events"`
}

jsonアノテーションにダブルコーテーションが足りてなくてエラーが検出されたようです。
なるほど。こんな感じでgo vetコマンドは使えるんですね。
ということで、これからはコードを書いたあとは意識的にgo vetコマンドを実行してエラーが検出されるかどうか確認しようと思います!

こんなものもありました


go vetコマンドには様々なサブコマンドがあります。(僕はあまり使いませんが)
その中でもshadowというサブコマンドについて詳しく書かれていた記事があったので、リンクを貼っておきます。
go vetコマンドについて更に詳しく知りたい方は以下をどうぞ。
go vet の shadow を知る developers.eure.jp