[インデックス 17538] ファイルの概要
このコミットは、Goコマンドラインツールにおけるgo install x.go
コマンドの挙動を修正するものです。具体的には、GOBIN
環境変数が設定されていない場合に、コマンドラインで指定された.go
ファイル(例: go install main.go
)のインストール先が見つからないというエラーメッセージを改善し、より適切なエラーハンドリングを提供する変更です。
コミット
commit 159c2b7e46f0b8293f1eed66ebec70ca845ac591
Author: Russ Cox <rsc@golang.org>
Date: Tue Sep 10 14:41:07 2013 -0400
cmd/go: fix error for 'go install x.go' when GOBIN is not set
Fixes #6191.
Fixes #5426.
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/13234052
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/159c2b7e46f0b8293f1eed66ebec70ca845ac591
元コミット内容
cmd/go: fix error for 'go install x.go' when GOBIN is not set
このコミットは、GOBIN
環境変数が設定されていない状態でgo install x.go
のように特定の.go
ファイルを指定してインストールしようとした際に発生するエラーメッセージを修正することを目的としています。
変更の背景
この変更は、GoのIssue #6191と #5426を修正するために行われました。
- Issue #6191: このIssueは、
GOBIN
が設定されていない場合にgo install foo.go
を実行すると、go install: no install location for directory /path/to/foo.go outside GOPATH
という誤解を招くエラーメッセージが表示されることを指摘していました。本来は、コマンドラインで指定されたファイルに対するインストール先がないことを明確に伝えるべきでした。 - Issue #5426: このIssueも同様に、
go install
が特定の.go
ファイルを引数として受け取った際に、GOBIN
が設定されていない場合の挙動に関するものでした。ユーザーは、go install
がパッケージ名ではなくファイル名を引数として受け取った場合に、どこに実行可能ファイルがインストールされるべきかについて混乱していました。
これらのIssueは、go install
コマンドがパッケージパス(例: go install github.com/user/repo/cmd/myprog
)と直接ファイルパス(例: go install main.go
)の両方を受け入れるというGoの設計に起因するものでした。パッケージパスの場合、GOPATH/bin
またはGOBIN
にインストールされますが、ファイルパスの場合の挙動が不明確であり、特にGOBIN
が設定されていない場合に適切なエラーメッセージが表示されないという問題がありました。
このコミットは、この曖昧さを解消し、ユーザーがより分かりやすいエラーメッセージを受け取れるようにすることで、開発体験を向上させることを目指しています。
前提知識の解説
このコミットを理解するためには、以下のGoの概念とコマンドに関する知識が必要です。
-
go install
コマンド:go install
はGoのビルドツールチェーンの一部であり、Goのパッケージをコンパイルし、その結果生成される実行可能ファイルやライブラリを標準のインストール場所に配置するために使用されます。- パッケージのインストール:
go install <package_path>
のようにパッケージパスを指定すると、そのパッケージがコンパイルされ、実行可能ファイル(main
パッケージの場合)は$GOBIN
または$GOPATH/bin
に、ライブラリ(非main
パッケージの場合)は$GOPATH/pkg
にインストールされます。 - ファイルのインストール:
go install <file.go>
のように直接.go
ファイルを指定することもできます。この場合、指定されたファイルが属するディレクトリが一時的なパッケージとして扱われ、コンパイルされます。生成された実行可能ファイルは通常$GOBIN
または$GOPATH/bin
にインストールされますが、GOBIN
が設定されていない場合はインストール先が不明確になるという問題がありました。
- パッケージのインストール:
-
GOPATH
環境変数:GOPATH
は、Goのワークスペースのルートディレクトリを指定する環境変数です。Goのソースコード、コンパイルされたパッケージ、および実行可能ファイルは、このGOPATH
の構造に従って配置されます。 一般的なGOPATH
の構造は以下の通りです。$GOPATH/src
: ソースコードが配置されます。$GOPATH/pkg
: コンパイルされたパッケージアーカイブが配置されます。$GOPATH/bin
:go install
によって生成された実行可能ファイルが配置されます。
-
GOBIN
環境変数:GOBIN
は、go install
コマンドによって生成された実行可能ファイルを配置するディレクトリを明示的に指定するための環境変数です。GOBIN
が設定されている場合、go install
は常に指定されたGOBIN
ディレクトリに実行可能ファイルをインストールします。GOBIN
が設定されていない場合、デフォルトで$GOPATH/bin
にインストールされます。 -
パッケージの解決とビルドプロセス: Goのビルドプロセスでは、ソースファイルがどのパッケージに属するか、そのパッケージがどこにインストールされるべきかを決定します。
go install
は、この解決プロセスの一部として、最終的な出力ファイルの配置場所を決定します。
このコミットは、特にGOBIN
が設定されていない状況で、go install
に直接.go
ファイルを渡した場合のインストール先の決定ロジックと、それに関連するエラーメッセージの改善に焦点を当てています。
技術的詳細
このコミットの技術的な核心は、go install
コマンドが、コマンドラインで直接指定された.go
ファイル(例: go install main.go
)と、インポートパスで指定されたパッケージ(例: go install github.com/user/repo
)を区別し、それぞれに対して適切なインストール場所のチェックとエラーメッセージを生成するように変更された点にあります。
変更は主に以下の3つのファイルで行われています。
-
src/cmd/go/pkg.go
:Package
構造体に新しいフィールドcmdline bool
が追加されました。このフィールドは、そのPackage
がコマンドラインで直接指定された.go
ファイルから生成されたものであるかどうかを示すフラグとして機能します。 -
src/cmd/go/build.go
:goFilesPackage
関数内で、Package
構造体のcmdline
フィールドがtrue
に設定されるようになりました。これは、goFilesPackage
がコマンドラインで指定された.go
ファイル群からPackage
を構築する際に呼び出されるためです。runInstall
関数内で、インストール場所のチェックロジックが変更されました。以前は、p.Target == ""
(インストール先が未定義)かつ!p.Standard || p.ImportPath != "unsafe"
(標準パッケージやunsafe
パッケージではない)場合に、p.ConflictDir != ""
(GOPATH外のディレクトリで、かつGOPATH内の別のパッケージと競合している)かどうかでエラーメッセージを分岐していました。 このコミットでは、このチェックの前にp.cmdline
がtrue
であるかどうかの条件が追加されました。- もし
p.cmdline
がtrue
であれば、つまりコマンドラインで.go
ファイルが指定された場合、GOBIN
が設定されていないことによるインストール先の不足を明示するエラーメッセージ「go install: no install location for .go files listed on command line (GOBIN not set)
」が表示されるようになりました。 p.cmdline
がfalse
の場合(通常のパッケージインストールの場合)は、以前と同様のロジックが適用され、GOPATH
外のディレクトリや競合するディレクトリに関するエラーメッセージが表示されます。
- もし
-
src/cmd/go/test.bash
: テストスクリプトが更新され、GOBIN
が設定されていない状態でgo install testdata/src/go-cmd-test/helloworld.go
を実行した場合に、期待される新しいエラーメッセージ「no install location for .go files listed on command line
」が正しく出力されることを検証するテストが追加されました。これにより、修正が意図通りに機能していることが確認されます。
この変更により、go install
コマンドは、ユーザーが意図したインストール方法(パッケージ名 vs. ファイル名)をより正確に判断し、それに応じた適切なエラーメッセージを提供できるようになりました。これは、Goツールのユーザーフレンドリーさを向上させる重要な改善です。
コアとなるコードの変更箇所
src/cmd/go/build.go
--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -311,7 +311,9 @@ func runInstall(cmd *Command, args []string) {
for _, p := range pkgs {
if p.Target == "" && (!p.Standard || p.ImportPath != "unsafe") {
- if p.ConflictDir != "" {
+ if p.cmdline {
+ errorf("go install: no install location for .go files listed on command line (GOBIN not set)")
+ } else if p.ConflictDir != "" {
errorf("go install: no install location for %s: hidden by %s", p.Dir, p.ConflictDir)
} else {
errorf("go install: no install location for directory %s outside GOPATH", p.Dir)
@@ -486,6 +488,7 @@ func goFilesPackage(gofiles []string) *Package {
bp, err := ctxt.ImportDir(dir, 0)
pkg := new(Package)
pkg.local = true
+ pkg.cmdline = true
pkg.load(&stk, bp, err)
pkg.localPrefix = dirToImportPath(dir)
pkg.ImportPath = "command-line-arguments"
src/cmd/go/pkg.go
--- a/src/cmd/go/pkg.go
+++ b/src/cmd/go/pkg.go
@@ -82,6 +82,7 @@ type Package struct {
fake bool // synthesized package
forceBuild bool // this package must be rebuilt
forceLibrary bool // this package is a library (even if named "main")
+ cmdline bool // defined by files listed on command line
local bool // imported via local path (./ or ../)
localPrefix string // interpret ./ and ../ imports relative to this prefix
exeName string // desired name for temporary executable
src/cmd/go/test.bash
--- a/src/cmd/go/test.bash
+++ b/src/cmd/go/test.bash
@@ -150,11 +150,16 @@ fi
# Without $GOBIN set, installing a program outside $GOPATH should fail
# (there is nowhere to install it).
-TEST install without destination
-if ./testgo install testdata/src/go-cmd-test/helloworld.go; then
+TEST install without destination fails
+if ./testgo install testdata/src/go-cmd-test/helloworld.go 2>testdata/err; then
echo "go install testdata/src/go-cmd-test/helloworld.go should have failed, did not"
ok=false
+elif ! grep 'no install location for .go files listed on command line' testdata/err; then
+ echo "wrong error:"
+ cat testdata/err
+ ok=false
fi
+rm -f testdata/err
# With $GOBIN set, should install there.
TEST install to GOBIN '(command-line package)'
コアとなるコードの解説
src/cmd/go/pkg.go
の変更
Package
構造体は、Goのビルドシステムが扱うパッケージのメタデータを保持します。ここに追加されたcmdline bool
フィールドは、このPackage
インスタンスが、go install main.go
のようにコマンドラインで直接.go
ファイルが指定されたことによって生成されたものであるかを識別するためのフラグです。これにより、Goツールはパッケージのソースがどこにあるかだけでなく、そのパッケージがどのように指定されたか(インポートパスか、直接ファイルか)というコンテキストを保持できるようになります。
src/cmd/go/build.go
の変更
-
goFilesPackage
関数: この関数は、コマンドラインで指定された一連の.go
ファイルからPackage
構造体を構築する際に呼び出されます。変更点として、pkg.cmdline = true
が追加されました。これにより、コマンドラインで指定されたファイルから生成されたPackage
インスタンスには、cmdline
フラグが立てられるようになります。 -
runInstall
関数: この関数はgo install
コマンドの主要なロジックを含んでいます。特に、インストール先の決定とエラーハンドリングを担当します。 変更されたif
文の条件は以下のようになっています。if p.Target == "" && (!p.Standard || p.ImportPath != "unsafe") { if p.cmdline { errorf("go install: no install location for .go files listed on command line (GOBIN not set)") } else if p.ConflictDir != "" { errorf("go install: no install location for %s: hidden by %s", p.Dir, p.ConflictDir) } else { errorf("go install: no install location for directory %s outside GOPATH", p.Dir) } }
p.Target == ""
は、パッケージのビルドターゲット(実行可能ファイルのパスなど)がまだ決定されていないことを意味します。(!p.Standard || p.ImportPath != "unsafe")
は、標準ライブラリやunsafe
パッケージではないことを確認します。これらのパッケージは特別な扱いを受けるため、通常はインストールされません。if p.cmdline
: ここが今回の変更の核心です。もしp.cmdline
がtrue
であれば、それはユーザーがgo install main.go
のように直接.go
ファイルを指定したことを意味します。この場合、GOBIN
が設定されていないと実行可能ファイルのインストール先が不明確になるため、「go install: no install location for .go files listed on command line (GOBIN not set)
」という、より具体的で分かりやすいエラーメッセージが表示されます。このメッセージは、ユーザーにGOBIN
を設定するか、GOPATH
内で作業することを促します。else if p.ConflictDir != ""
:p.cmdline
がfalse
の場合(つまり、通常のパッケージインストールの場合)に、GOPATH
内の別のパッケージと競合しているディレクトリからのインストールを試みた場合に表示されるエラーメッセージです。else
: 上記のいずれにも該当しない場合(例えば、GOPATH
外のディレクトリにあるパッケージをインストールしようとした場合)に表示される一般的なエラーメッセージです。
このロジックの変更により、go install
は、ユーザーがコマンドラインで.go
ファイルを直接指定した場合に、より的確なエラーメッセージを提供できるようになり、ユーザーの混乱を減らすことができます。
src/cmd/go/test.bash
の変更
テストスクリプトの変更は、この修正が正しく機能していることを確認するためのものです。
以前のテストは単にgo install testdata/src/go-cmd-test/helloworld.go
が失敗することだけを検証していましたが、新しいテストでは、エラー出力が期待される新しいエラーメッセージ「no install location for .go files listed on command line
」を含んでいることをgrep
コマンドで確認しています。これにより、エラーメッセージの正確性も保証されます。
関連リンク
- Go CL 13234052: https://golang.org/cl/13234052
参考にした情報源リンク
- Go Issue #6191:
go install foo.go
fails with misleading error when GOBIN not set (おそらくGoのIssueトラッカーで検索可能) - Go Issue #5426:
go install
with file argument and no GOBIN (おそらくGoのIssueトラッカーで検索可能) - Go Modules Reference: https://go.dev/doc/modules/ (Go Modules導入後の情報も含まれるが、GOPATH/GOBINの概念は共通)
- The Go Programming Language Specification: https://go.dev/ref/spec
- Go Command Documentation:
go help install
(ローカル環境で実行可能)
[インデックス 17538] ファイルの概要
このコミットは、Goコマンドラインツールにおけるgo install x.go
コマンドの挙動を修正するものです。具体的には、GOBIN
環境変数が設定されていない場合に、コマンドラインで指定された.go
ファイル(例: go install main.go
)のインストール先が見つからないというエラーメッセージを改善し、より適切なエラーハンドリングを提供する変更です。
コミット
commit 159c2b7e46f0b8293f1eed66ebec70ca845ac591
Author: Russ Cox <rsc@golang.org>
Date: Tue Sep 10 14:41:07 2013 -0400
cmd/go: fix error for 'go install x.go' when GOBIN is not set
Fixes #6191.
Fixes #5426.
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/13234052
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/159c2b7e46f0b8293f1eed66ebec70ca845ac591
元コミット内容
cmd/go: fix error for 'go install x.go' when GOBIN is not set
このコミットは、GOBIN
環境変数が設定されていない状態でgo install x.go
のように特定の.go
ファイルを指定してインストールしようとした際に発生するエラーメッセージを修正することを目的としています。
変更の背景
この変更は、GoのIssue #6191と #5426を修正するために行われました。
- Issue #6191: このIssueは、
GOBIN
が設定されていない場合にgo install foo.go
を実行すると、go install: no install location for directory /path/to/foo.go outside GOPATH
という誤解を招くエラーメッセージが表示されることを指摘していました。本来は、コマンドラインで指定されたファイルに対するインストール先がないことを明確に伝えるべきでした。 - Issue #5426: このIssueも同様に、
go install
が特定の.go
ファイルを引数として受け取った際に、GOBIN
が設定されていない場合の挙動に関するものでした。ユーザーは、go install
がパッケージ名ではなくファイル名を引数として受け取った場合に、どこに実行可能ファイルがインストールされるべきかについて混乱していました。
これらのIssueは、go install
コマンドがパッケージパス(例: go install github.com/user/repo/cmd/myprog
)と直接ファイルパス(例: go install main.go
)の両方を受け入れるというGoの設計に起因するものでした。パッケージパスの場合、GOPATH/bin
またはGOBIN
にインストールされますが、ファイルパスの場合の挙動が不明確であり、特にGOBIN
が設定されていない場合に適切なエラーメッセージが表示されないという問題がありました。
このコミットは、この曖昧さを解消し、ユーザーがより分かりやすいエラーメッセージを受け取れるようにすることで、開発体験を向上させることを目指しています。
前提知識の解説
このコミットを理解するためには、以下のGoの概念とコマンドに関する知識が必要です。
-
go install
コマンド:go install
はGoのビルドツールチェーンの一部であり、Goのパッケージをコンパイルし、その結果生成される実行可能ファイルやライブラリを標準のインストール場所に配置するために使用されます。- パッケージのインストール:
go install <package_path>
のようにパッケージパスを指定すると、そのパッケージがコンパイルされ、実行可能ファイル(main
パッケージの場合)は$GOBIN
または$GOPATH/bin
に、ライブラリ(非main
パッケージの場合)は$GOPATH/pkg
にインストールされます。 - ファイルのインストール:
go install <file.go>
のように直接.go
ファイルを指定することもできます。この場合、指定されたファイルが属するディレクトリが一時的なパッケージとして扱われ、コンパイルされます。生成された実行可能ファイルは通常$GOBIN
または$GOPATH/bin
にインストールされますが、GOBIN
が設定されていない場合はインストール先が不明確になるという問題がありました。
- パッケージのインストール:
-
GOPATH
環境変数:GOPATH
は、Goのワークスペースのルートディレクトリを指定する環境変数です。Goのソースコード、コンパイルされたパッケージ、および実行可能ファイルは、このGOPATH
の構造に従って配置されます。 一般的なGOPATH
の構造は以下の通りです。$GOPATH/src
: ソースコードが配置されます。$GOPATH/pkg
: コンパイルされたパッケージアーカイブが配置されます。$GOPATH/bin
:go install
によって生成された実行可能ファイルが配置されます。
-
GOBIN
環境変数:GOBIN
は、go install
コマンドによって生成された実行可能ファイルを配置するディレクトリを明示的に指定するための環境変数です。GOBIN
が設定されている場合、go install
は常に指定されたGOBIN
ディレクトリに実行可能ファイルをインストールします。GOBIN
が設定されていない場合、デフォルトで$GOPATH/bin
にインストールされます。 -
パッケージの解決とビルドプロセス: Goのビルドプロセスでは、ソースファイルがどのパッケージに属するか、そのパッケージがどこにインストールされるべきかを決定します。
go install
は、この解決プロセスの一部として、最終的な出力ファイルの配置場所を決定します。
このコミットは、特にGOBIN
が設定されていない状況で、go install
に直接.go
ファイルを渡した場合のインストール先の決定ロジックと、それに関連するエラーメッセージの改善に焦点を当てています。
技術的詳細
このコミットの技術的な核心は、go install
コマンドが、コマンドラインで直接指定された.go
ファイル(例: go install main.go
)と、インポートパスで指定されたパッケージ(例: go install github.com/user/repo
)を区別し、それぞれに対して適切なインストール場所のチェックとエラーメッセージを生成するように変更された点にあります。
変更は主に以下の3つのファイルで行われています。
-
src/cmd/go/pkg.go
:Package
構造体に新しいフィールドcmdline bool
が追加されました。このフィールドは、そのPackage
がコマンドラインで直接指定された.go
ファイルから生成されたものであるかどうかを示すフラグとして機能します。 -
src/cmd/go/build.go
:goFilesPackage
関数内で、Package
構造体のcmdline
フィールドがtrue
に設定されるようになりました。これは、goFilesPackage
がコマンドラインで指定された.go
ファイル群からPackage
を構築する際に呼び出されるためです。runInstall
関数内で、インストール場所のチェックロジックが変更されました。以前は、p.Target == ""
(インストール先が未定義)かつ!p.Standard || p.ImportPath != "unsafe"
(標準パッケージやunsafe
パッケージではない)場合に、p.ConflictDir != ""
(GOPATH外のディレクトリで、かつGOPATH内の別のパッケージと競合している)かどうかでエラーメッセージを分岐していました。 このコミットでは、このチェックの前にp.cmdline
がtrue
であるかどうかの条件が追加されました。- もし
p.cmdline
がtrue
であれば、つまりコマンドラインで.go
ファイルが指定された場合、GOBIN
が設定されていないことによるインストール先の不足を明示するエラーメッセージ「go install: no install location for .go files listed on command line (GOBIN not set)
」が表示されるようになりました。 p.cmdline
がfalse
の場合(通常のパッケージインストールの場合)は、以前と同様のロジックが適用され、GOPATH
外のディレクトリや競合するディレクトリに関するエラーメッセージが表示されます。
- もし
-
src/cmd/go/test.bash
: テストスクリプトが更新され、GOBIN
が設定されていない状態でgo install testdata/src/go-cmd-test/helloworld.go
を実行した場合に、期待される新しいエラーメッセージ「no install location for .go files listed on command line
」が正しく出力されることを検証するテストが追加されました。これにより、修正が意図通りに機能していることが確認されます。
この変更により、go install
コマンドは、ユーザーが意図したインストール方法(パッケージ名 vs. ファイル名)をより正確に判断し、それに応じた適切なエラーメッセージを提供できるようになりました。これは、Goツールのユーザーフレンドリーさを向上させる重要な改善です。
コアとなるコードの変更箇所
src/cmd/go/build.go
--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -311,7 +311,9 @@ func runInstall(cmd *Command, args []string) {
for _, p := range pkgs {
if p.Target == "" && (!p.Standard || p.ImportPath != "unsafe") {
- if p.ConflictDir != "" {
+ if p.cmdline {
+ errorf("go install: no install location for .go files listed on command line (GOBIN not set)")
+ } else if p.ConflictDir != "" {
errorf("go install: no install location for %s: hidden by %s", p.Dir, p.ConflictDir)
} else {
errorf("go install: no install location for directory %s outside GOPATH", p.Dir)
@@ -486,6 +488,7 @@ func goFilesPackage(gofiles []string) *Package {
bp, err := ctxt.ImportDir(dir, 0)
pkg := new(Package)
pkg.local = true
+ pkg.cmdline = true
pkg.load(&stk, bp, err)
pkg.localPrefix = dirToImportPath(dir)
pkg.ImportPath = "command-line-arguments"
src/cmd/go/pkg.go
--- a/src/cmd/go/pkg.go
+++ b/src/cmd/go/pkg.go
@@ -82,6 +82,7 @@ type Package struct {
fake bool // synthesized package
forceBuild bool // this package must be rebuilt
forceLibrary bool // this package is a library (even if named "main")
+ cmdline bool // defined by files listed on command line
local bool // imported via local path (./ or ../)
localPrefix string // interpret ./ and ../ imports relative to this prefix
exeName string // desired name for temporary executable
src/cmd/go/test.bash
--- a/src/cmd/go/test.bash
+++ b/src/cmd/go/test.bash
@@ -150,11 +150,16 @@ fi
# Without $GOBIN set, installing a program outside $GOPATH should fail
# (there is nowhere to install it).
-TEST install without destination
-if ./testgo install testdata/src/go-cmd-test/helloworld.go; then
+TEST install without destination fails
+if ./testgo install testdata/src/go-cmd-test/helloworld.go 2>testdata/err; then
echo "go install testdata/src/go-cmd-test/helloworld.go should have failed, did not"
ok=false
+elif ! grep 'no install location for .go files listed on command line' testdata/err; then
+ echo "wrong error:"
+ cat testdata/err
+ ok=false
fi
+rm -f testdata/err
# With $GOBIN set, should install there.
TEST install to GOBIN '(command-line package)'
コアとなるコードの解説
src/cmd/go/pkg.go
の変更
Package
構造体は、Goのビルドシステムが扱うパッケージのメタデータを保持します。ここに追加されたcmdline bool
フィールドは、このPackage
インスタンスが、go install main.go
のようにコマンドラインで直接.go
ファイルが指定されたことによって生成されたものであるかを識別するためのフラグです。これにより、Goツールはパッケージのソースがどこにあるかだけでなく、そのパッケージがどのように指定されたか(インポートパスか、直接ファイルか)というコンテキストを保持できるようになります。
src/cmd/go/build.go
の変更
-
goFilesPackage
関数: この関数は、コマンドラインで指定された一連の.go
ファイルからPackage
構造体を構築する際に呼び出されます。変更点として、pkg.cmdline = true
が追加されました。これにより、コマンドラインで指定されたファイルから生成されたPackage
インスタンスには、cmdline
フラグが立てられるようになります。 -
runInstall
関数: この関数はgo install
コマンドの主要なロジックを含んでいます。特に、インストール先の決定とエラーハンドリングを担当します。 変更されたif
文の条件は以下のようになっています。if p.Target == "" && (!p.Standard || p.ImportPath != "unsafe") { if p.cmdline { errorf("go install: no install location for .go files listed on command line (GOBIN not set)") } else if p.ConflictDir != "" { errorf("go install: no install location for %s: hidden by %s", p.Dir, p.ConflictDir) } else { errorf("go install: no install location for directory %s outside GOPATH", p.Dir) } }
p.Target == ""
は、パッケージのビルドターゲット(実行可能ファイルのパスなど)がまだ決定されていないことを意味します。(!p.Standard || p.ImportPath != "unsafe")
は、標準ライブラリやunsafe
パッケージではないことを確認します。これらのパッケージは特別な扱いを受けるため、通常はインストールされません。if p.cmdline
: ここが今回の変更の核心です。もしp.cmdline
がtrue
であれば、それはユーザーがgo install main.go
のように直接.go
ファイルを指定したことを意味します。この場合、GOBIN
が設定されていないと実行可能ファイルのインストール先が不明確になるため、「go install: no install location for .go files listed on command line (GOBIN not set)
」という、より具体的で分かりやすいエラーメッセージが表示されます。このメッセージは、ユーザーにGOBIN
を設定するか、GOPATH
内で作業することを促します。else if p.ConflictDir != ""
:p.cmdline
がfalse
の場合(つまり、通常のパッケージインストールの場合)に、GOPATH
内の別のパッケージと競合しているディレクトリからのインストールを試みた場合に表示されるエラーメッセージです。else
: 上記のいずれにも該当しない場合(例えば、GOPATH
外のディレクトリにあるパッケージをインストールしようとした場合)に表示される一般的なエラーメッセージです。
このロジックの変更により、go install
は、ユーザーがコマンドラインで.go
ファイルを直接指定した場合に、より的確なエラーメッセージを提供できるようになり、ユーザーの混乱を減らすことができます。
src/cmd/go/test.bash
の変更
テストスクリプトの変更は、この修正が正しく機能していることを確認するためのものです。
以前のテストは単にgo install testdata/src/go-cmd-test/helloworld.go
が失敗することだけを検証していましたが、新しいテストでは、エラー出力が期待される新しいエラーメッセージ「no install location for .go files listed on command line
」を含んでいることをgrep
コマンドで確認しています。これにより、エラーメッセージの正確性も保証されます。
関連リンク
- Go CL 13234052: https://golang.org/cl/13234052
参考にした情報源リンク
- Go Issue #6191: (Web検索では直接的なリンクが見つかりませんでした)
- Go Issue #5426: (Web検索では直接的なリンクが見つかりませんでした)
- Go Modules Reference: https://go.dev/doc/modules/ (Go Modules導入後の情報も含まれるが、GOPATH/GOBINの概念は共通)
- The Go Programming Language Specification: https://go.dev/ref/spec
- Go Command Documentation:
go help install
(ローカル環境で実行可能)