コマンド@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)
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
ファイルに定義がない場合は、これを追加する。
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
ファイルによって実際にインストールされたモジュールが自動的に実装される。
モジュールごとのチェックサムが記録されるため、前回のインストール時と比較して、モジュールに変更があるか否かを検知できる。