コマンド@Go¶
はじめに¶
本サイトにつきまして、以下をご認識のほど宜しくお願いいたします。
01. goコマンド¶
build¶
▼ buildとは¶
指定したパスをビルド対象として、ビルドのアーティファクトを作成する。
foo_test.go ファイルはビルドから自動的に除外される。
アーティファクトの出力先を指定しない場合に、
# cmdディレクトリをビルド対象として、ルートディレクトリにcmdアーティファクトを作成する。
$ go build ./cmd
もし、ビルドのエラー時に終了ステータスのみが返却され、原因が不明の場合、panic 関数が原因を握りつぶしている可能性を考える。
exit status 2. Docker build ran into internal error. Please retry. If this keeps happening, please open an issue..
▼ -o¶
指定したパスにビルドのアーティファクトを作成する。
ビルド対象パスを指定しない場合、ルートディレクトリのgoファイルをビルドの対象とする。
# ルートディレクトリ内のgoファイルをビルド対象として
# $HOME/go/binディレクトリにルートディレクトリ名アーティファクトを作成する。
$ go build -o $HOME/go/bin
また、指定したパス内のgoファイルをビルド対象として、指定したパスにビルドのアーティファクトを作成もできる。
# cmdディレクトリ内のgoファイルをビルド対象として
# $HOME/go/binディレクトリにcmdアーティファクトを作成する。
$ go build -o $HOME/go/bin ./cmd
補足として、事前のインストールに失敗に、ビルド対象が存在していないと以下のようなエラーになってしまう。
package foo is not in GOROOT (/usr/local/go/src/foo)
commit¶
▼ -m¶
コミットメッセージを設定する。
空コミットでよく使う。
$ git commit --allow-empty -m "first commit"
clean¶
モジュールのキャッシュを削除する。
ローカルマシンでの開発中に go install コマンドを実行しても、モジュールをアップグレードできない場合に使用する。
$ go clean --modcache
$ go mod tidy
env¶
▼ envとは¶
Goに関する環境変数を出力する。
*実装例*
$ go env
GO111MODULE="on"
GOARCH="amd64"
...
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build887404645=/tmp/go-build -gno-record-gcc-switches"
fmt¶
▼ fmtとは¶
指定したパスのファイルのインデントを整形する。
パスとして『./...』を指定して、再帰的に実行するのがおすすめ。
$ go fmt ./...
install¶
▼ installとは¶
go get コマンドとは異なり、Goのバイナリをモジュールとしてでなく、ツールとしてグローバルにインストールする。
コードと外部モジュールに対して build コマンドを実行することにより、$GOPATH 以下の bin ディレクトリまたは pkg ディレクトリにインストール (配置) する。
内部または外部のコードからビルドされたアーティファクト (バイナリファイル) であれば bin ディレクトリ配下に配置し、それ以外 (例:.a ファイル) であれば pkg ディレクトリ配下に配置する。
# asdfでGoをインストールしている場合は、go installコマンドの前に`PATH`を設定しておく
$ export PATH="$(go env GOPATH)/bin:$PATH"
$ go install
なお、インストールしたモジュールで replace を使用している場合、クローンしてから直接インストールする必要がある。
$ git clone <モジュールのリポジトリ>
$ cd <バイナリのディレクトリ>
$ go install
バイナリは、パスが通っていないため、直接パスを指定して実行する必要がある。
$ ${GOPATH}/bin/foo-package --version
▼ 最新バージョンの指定¶
HEAD を指定すると、最新のコミットIDを指定できる。
複数のブランチがある場合は、時系列的に最新のコミットIDである。
$ go install <モジュール名>@HEAD
▼ バイナリのアンインストール¶
go install コマンドでインストールしたバイナリは、rm コマンドで直接削除する必要がある。
$ ls ${GOPATH}/bin
foo-package
$ rm ${GOPATH}/bin/foo-package
run¶
▼ runとは¶
go build コマンドを実行しつつ、バイナリを実行する。
ソースコードを変更した後に動作を簡易的に確認する場合に便利である。
ただ、log モジュールなど処理中のメッセージは表示されず、main.go ファイルの実行結果しかわからないため、エラーのデバッグには使いにくい。
$ go run ./...
test¶
▼ testとは¶
指定したパスの foo_test.go ファイルで『Test』から始まるテスト関数を実行する。
testディレクトリ内を再帰的に実行するのがおすすめ。
$ go test ./...
▼ -v¶
テスト時にテストの実施時間を出力する。
$ go test -v ./...
▼ -cover¶
テスト時に、foo_test.go ファイルがあるモジュール内ファイルの命令網羅の網羅率を解析する。
反対に、foo_test.go ファイルがなければ、そのモジュールの網羅率は解析しない。
$ go test -cover ./...
▼ -coverpkg¶
モジュールを指定して、網羅率を解析する。
デフォルトではテストコードがあるモジュールしか解析しないため、全てのモジュールを含めて解析するために ./... を指定する。
$ go test -coverpkg=./... -coverprofile=coverage.txt ./...
▼ -coverprofile¶
網羅率を解析し、結果からカバレッジレポートを作成する。
$ go test -coverprofile=coverage.txt ./...
tool¶
▼ cover¶
カバレッジレポートを使用して、特定のコンポーネントでのカバレッジを算出する。
モジュール単位、関数単位 (-func) 、全体、のカバレッジを指定できる。
$ go tool cover -func coverage.txt
version¶
▼ -m¶
バイナリで使用しているGoのバージョンと、モジュールのバージョンを出力する。
$ go version -m <Goのバイナリのパス>
<Goのバイナリのパス>: go 1.19.5
...
vet¶
▼ vetとは¶
指定したパスのファイルに対して、静的解析を実施する。
パスとして『./...』を指定して、再帰的に実行するのがおすすめ。
$ go vet ./...
02. モジュール管理系コマンド¶
大前提¶
Goでは、思想的にモジュールのバージョンを固定して運用せず、常に新しいバージョンを強制的に利用させるような仕組みがある。
get¶
▼ getとは¶
指定したパスからモジュールをダウンロードし、これに対して install コマンドを実行する。
また、go.mod ファイルも更新する。
これにより、内部または外部のコードからビルドされたアーティファクト (バイナリファイル) であれば bin ディレクトリ配下に配置し、それ以外 (例:.a ファイル) であれば pkg ディレクトリ配下に配置する。
go get コマンドは不用意に go.mod ファイル上の他のモジュールの定義も更新してしまうため、非推奨である。
# インストールの場合
$ go get <ドメインをルートとしたURL>@<バージョン>
go: downloading <ドメインをルートとしたURL> <バージョン>
go: added <ドメインをルートとしたURL> <バージョン>
# アップグレードの場合
$ go get <ドメインをルートとしたURL>@<バージョン>
go: downloading <ドメインをルートとしたURL> <バージョン>
go: upgraded <ドメインをルートとしたURL> <バージョン>
▼ go mod tidyとの使い分け¶
先にインストールしたモジュールのバージョンが優先になり、このバージョンを基準として他のモジュールのバージョンが決まる。
そのため、開発者によって結果が変わってしまう。
その反面、go mod tidy コマンドは同じ結果になる。
もし全てのモジュールのバージョンを開発者に限らず揃えたいなら、go mod tidy コマンドを使用する。
mod edit¶
▼ mod editとは¶
go.mod ファイルで指定しているバージョンを変更する。
$ go mod edit
mod tidy¶
▼ mod tidyとは¶
importで指定されているがgo getコマンドでインストールされていない場合は、これをインストールする。importで指定のないモジュールは、go.modファイルとgo.sumファイルから削除する。importで指定されているがgo.modファイルとgo.sumファイルに定義がない場合は、これを追加する。- アップグレード可能なモジュールはバージョンを変更する。
$ go mod tidy
もし go.sum ファイルにモジュールの指定があるのにも関わらず、以下のようなエラー (missing go.sum entry) が出るときは、go mod tidy コマンドを実行して go.sum ファイルを更新する必要がある。
cmd/main.go:4:5: missing go.sum entry for module providing package github.com/foo/foo-package (imported by github.com/hiroki-it/bar/cmd); to add:
go get github.com/hiroki-hasegawa/bar/cmd
▼ -go¶
go.mod ファイルに記載のGoのバージョンを上書きしつつ、go.sum ファイルを更新する。
ただし、-go オプションは推奨バージョンを設定できるだけで、これを守らない場合もある。
$ go mod tidy -go <バージョン>
▼ -v¶
import していないために go.mod ファイルから削除したモジュールを、標準出力に出力する。
$ go mod tidy -v
unused <go.modファイルから削除したモジュール>
▼ go getとの使い分け¶
go mod tidy コマンドは、たとえ -go オプションを使用しても、インストールするモジュールのバージョンを完全には制御できない。
(Goの思想的にも) できるだけ新しいバージョンを強制しようとするため、想定するバージョンよりも新しいモジュールをインストールしてしまう可能性がある。
そのため、特定のバージョン (特にコミットIDでの指定) は go get コマンドでインストールする必要がある。
ただ推奨としては、Goの思想に則り、go mod tidy コマンドを実行して常に新しいバージョンを使用するほうが良い。
mod verify¶
▼ mod verifyとは¶
go.sum ファイルが正しいかどうかを検証する。
$ go mod verify
all modules verified
▼ but does not contain package¶
インポートしたモジュールの依存先モジュールをダウンロードしたが、依存先モジュール内にモジュールがないことを表す。
// indiret で自動的に指定しているモジュールが新すぎる可能性がある。
この場合、// indiret のモジュールを手動で変更する。
*例*
// indiret で指定した依存先モジュール (go.module.io/foo-dependency) のバージョンが 1.27 になっている。
しかし、go.module.io/foo-dependency (1.27) には、bar モジュールがないためエラーになっている。
この場合、bar モジュールがあるバージョンに手動で書き換える必要がある。
$ go mod verify
go: finding module for package go.module.io/foo-dependency
github.com/foo imports
go.module.io/foo-dependency/bar: module go.module.io/foo-dependency@latest found (v1.27.0), but does not contain package go.module.io/foo-dependency/bar
mod download¶
▼ mod downloadとは¶
importで指定されているがgo getコマンドでインストールされていない場合は、これをインストールする。importで指定されているがgo.modファイルとgo.sumファイルに定義がない場合は、これを追加する。
02-02. モジュール管理系ファイル¶
go.mod ファイル¶
▼ go.mod ファイルとは¶
アプリケーションで必要なモジュールのバージョンを設定する。
モジュール内に go.mod ファイルがある場合、そこに記載のあるバージョンは最低限必要なバージョンになる。
基本的には、モジュールのURLやディレクトリ構成と同じにする。
module github.com/hiroki-hasegawa/foo-repository
go 1.16
▼ パブリックリポジトリから (リリース済み)¶
モジュール名とバージョンタグを使用して、パブリックリポジトリからリリース済みのモジュールをインポートする。
go mod tidy コマンドによって // indirect コメントのついたモジュールが実装される。
これは、インポートしたモジュールではなく、インポートしているモジュールが依存しているモジュールである。
注意点として、モジュール名は、使用したいモジュールの go.mod ファイルを参照すること。
module github.com/hiroki-hasegawa/foo-repository
go 1.16
// 直接的に依存するモジュール (アプリで使用するモジュール)
require (
<モジュール名> <バージョンタグ>
github.com/foo v1.3.0
github.com/bar v1.0.0
)
// 間接的に依存するモジュール (アプリで使用するモジュールが依存するモジュール)
require (
github.com/baz v1.0.0 // indirect
)
import "github.com/bar"
func main() {
// 何らかの処理
}
▼ パブリックリポジトリから (開発中)¶
コミットIDやバージョンタグを使用して、パブリックリポジトリから開発中のモジュールをインポートする。
この場合、go get コマンドで特定のコミットIDやバージョンタグを指定し、モジュールをインストールする。
$ go get github.com/foo@<コミットID>
go: downloading github.com/foo v0.0.0-<コミット日時のタイムスタンプ>-<コミットID>
go: added github.com/foo v0.0.0-<コミット日時のタイムスタンプ>-<コミットID>
go get コマンドは、go.mod ファイルにインポート定義を追加する。
module github.com/hiroki-hasegawa/foo-repository
go 1.16
require (
github.com/foo v0.0.0-<コミット日時のタイムスタンプ>-<コミットID> // indirect
)
▼ プライベートリポジトリから¶
デフォルトでは、プライベートリポジトリのモジュールをインポートできない。
$ go get github.com/foo@<コミットID/バージョンタグ>
github.com/foo@v1.0.0: verifying module: github.com/foo@v1.0.0: reading https://sum.golang.org/lookup/github.com/foo@v1.0.0: 410 Gone
server response:
not found: github.com/foo@v1.0.0: invalid version: git ls-remote -q origin in /tmp/gopath/pkg/mod/cache/vcs/*****: exit status 128:
fatal: unable to look up github.com/foo.git (port 9418) (Name or service not known)
GOPRIVATE 変数にプライベートリポジトリのURLを設定することで、インポートできるようになる。
$ go env -w GOPRIVATE=github.com/foo.git,github.com/bar.git,...
▼ ローカルマシンから¶
ローカルマシンのみで使用する自前共有モジュールがあるとする。
foo-repository/
├── cmd/
│ └── hello.go
│
├── go.mod
├── go.sum
└── local-pkg/
├── go.mod # 各モジュールにgo.modを配置する。
└── module.go
// go.modファイル
module github.com/hiroki-hasegawa/foo-repository/local-pkg
go 1.16
この場合、パブリックリポジトリ上での自身のリポジトリからインポートせずに、replace 関数を使用してインポートする必要がある。
自前共有の全モジュールでモジュール名を置換する必要はなく、プロジェクトのルートパスについてのみ定義すれば良い。
パス実際、unknown revision のエラーで、バージョンを見つけられない。
module github.com/hiroki-hasegawa/foo-repository
go 1.16
replace github.com/hiroki-hasegawa/foo-repository/local-pkg => /
これらにより、ローカルマシンのモジュールをインポートできるようになる。
package main
import "local.packages/local-pkg"
func main() {
// 何らかの処理
}
go.sum ファイル¶
▼ go.sum ファイルとは¶
PHPにおける composer.lock ファイルに相当する。
go.mod ファイルによって実際にインストールされたモジュールが自動的に実装される。
モジュールごとのチェックサムが記録されるため、前回のインストール時と比較して、モジュールに変更があるか否かを検知できる。