goでネストしたパッケージの下にCLIツールを作る場合、go get時の挙動がよくわからなかったので試した。
gocmdtest ├── go.mod ├── go.sum └── tools ├── gocmdtestx │ └── cmd │ └── gocmdtestx.go # package main └── gocmdtesty └── cmd └── gocmdtesty.go # package main
このようなディレクトリ構造を例にする。
go get のパスをネストする・しないで何が変わるのか
この gocmdtest は、Go Modules的にはひとつのモジュールだが、次の2つの go get にどのような違いがあるか?
go get github.com/castaneai/gocmdtest go get github.com/castaneai/gocmdtest/tools/gocmdtestx/cmd
まず、パスを掘らずに一番上位だけをgo getしてみる。
$ go get github.com/castaneai/gocmdtest package github.com/castaneai/gocmdtest: no Go files in $GOPATH/src/github.com/castaneai/gocmdtest $ ls $GOPATH/src/github.com/castaneai/gocmdtest gocmdtest
なるほど。一番上をgo getしただけでは、tools/以下まで一緒にビルドされることはない。ただ、リポジトリ全体は$GOPATH/src/...以下にcloneされていた。
では、次はパスを掘ったgo getしてみる。
$ go get github.com/castaneai/gocmdtest/tools/gocmdtestx/cmd $ ls $GOPATH/src/github.com/castaneai/gocmdtest gocmdtest $ ls $GOPATH/bin cmd
だいたい最初のgo getと同じだが、$GOPATH/bin にcmdという名前でgocmdtestxの実行ファイルがビルドされていた。 なるほど。実行ファイルを $GOPATH/bin に配置したい場合は、こうやってフォルダを掘ってgo getすればいいということか〜。
実行ファイルの名前について
cmd/
をそのまま package main にしてしまうと、実行ファイル名が cmd になってしまうので、cmd/ツール名
までフォルダを掘ったほうがいいということだな。
golang-standards/に同じ内容が書かれていた。
https://github.com/golang-standards/project-layout/blob/master/cmd/README.md