Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 13530] ファイルの概要

このコミットは、Go言語のコマンドラインツール goenv サブコマンドの出力を改善するものです。具体的には、go env の出力に $GOPATH 環境変数の値を含めるようにし、さらに出力される環境変数リストをソートすることで、ユーザーがGoの環境設定をより簡単に確認できるように変更しています。

コミット

commit 7711e61031ef20dfa802a53e7c5eb932454112db
Author: Russ Cox <rsc@golang.org>
Date:   Mon Jul 30 00:22:42 2012 -0400

    cmd/go: show $GOPATH in 'go env' output
    
    Also, sort output.
    
    R=golang-dev, patrick, dave, iant
    CC=golang-dev, patrick
    https://golang.org/cl/6446064

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/7711e61031ef20dfa802a53e7c5eb932454112db

元コミット内容

cmd/go: show $GOPATH in 'go env' output

Also, sort output.

R=golang-dev, patrick, dave, iant
CC=golang-dev, patrick
https://golang.org/cl/6446064

変更の背景

Go言語の開発において、GOPATH は非常に重要な環境変数です。これはGoのソースコード、パッケージ、実行可能ファイルが配置されるワークスペースのルートディレクトリを指定します。開発者は、Goのプロジェクトをビルドしたり、依存関係を解決したりする際に、この GOPATH の設定が正しく行われていることを確認する必要があります。

go env コマンドは、Goのビルド環境に関する情報を表示するために提供されています。しかし、このコミット以前は、go env の出力に GOPATH が含まれていませんでした。そのため、ユーザーは GOPATH の値を確認するために別途 echo $GOPATH のようなシェルコマンドを実行する必要がありました。これは、Goの環境設定を一元的に確認したいユーザーにとって不便でした。

また、go env の出力順序が一定でなかったため、環境変数の確認や比較がしにくいという問題もありました。このコミットは、これらの問題を解決し、開発者の利便性を向上させることを目的としています。

前提知識の解説

go env コマンド

go env は、Goのビルド環境に関する情報を表示するコマンドです。Goのバージョン、オペレーティングシステム、アーキテクチャ、各種パスなど、Goプログラムのコンパイルや実行に影響を与える環境変数の現在の設定値を確認できます。例えば、go env GOROOT と実行すれば GOROOT の値だけを表示するといった使い方も可能です。

GOPATH 環境変数

GOPATH は、Go言語のワークスペースのルートディレクトリを指定する環境変数です。Go 1.11以降のGo Modulesの導入により、GOPATH の役割は以前よりも限定的になりましたが、Go Modulesを使用しないレガシーなプロジェクトや、特定の開発シナリオでは依然として重要です。

GOPATH ディレクトリの構造は通常以下のようになります。

  • src: ソースコードが配置されます。例えば、github.com/user/repo のリポジトリは $GOPATH/src/github.com/user/repo に配置されます。
  • pkg: コンパイルされたパッケージオブジェクトファイルが配置されます。
  • bin: go install でビルドされた実行可能ファイルが配置されます。

GOROOT 環境変数

GOROOT は、GoのSDK(Standard Development Kit)がインストールされているディレクトリのパスを指定する環境変数です。Goの標準ライブラリやツール群がここに格納されています。通常、ユーザーが手動で設定する必要はなく、Goのインストール時に自動的に設定されるか、go コマンドがデフォルトの場所を推測します。

GOBIN 環境変数

GOBIN は、go install コマンドでビルドされた実行可能ファイルが配置されるディレクトリのパスを指定する環境変数です。GOBIN が設定されていない場合、実行可能ファイルは $GOPATH/bin または $GOROOT/bin に配置されます。

envVar 構造体

Goの内部コードでは、環境変数を表現するために envVar のような構造体が使用されていると推測されます。これは、環境変数名とその値のペアを保持するためのシンプルなデータ構造です。

技術的詳細

このコミットの技術的な変更は、src/cmd/go/env.go ファイル内の mkEnv 関数に集中しています。この関数は、go env コマンドが最終的に表示する環境変数のリストを構築する役割を担っています。

変更前は、mkEnv 関数内で定義されている env スライス(Goの動的配列)に、GOROOTGOBINGOARCHGOCHARGOOSGOEXEGOHOSTARCHGOHOSTOSGOTOOLDIRGOGCCFLAGS といった環境変数がハードコードされた順序で追加されていました。

このコミットでは、以下の2つの主要な変更が行われています。

  1. GOPATH の追加: os.Getenv("GOPATH") を呼び出すことで、システム環境変数から GOPATH の現在の値を取得し、これを env スライスに追加しています。これにより、go env の出力に GOPATH の値が含まれるようになります。
  2. 出力のソート: env スライス内の要素の順序が変更され、アルファベット順に近くなるように再配置されています。これにより、go env の出力が常に一定の順序になり、視認性と比較可能性が向上します。具体的には、GOROOTGOBIN の位置が変更され、GOPATH がアルファベット順に適切な位置に挿入されています。

これらの変更は、envVar 構造体のスライスを構築する段階で行われるため、go env コマンドの実行時に動的に環境変数の値を取得し、ソートされた形で表示することが可能になります。

コアとなるコードの変更箇所

変更は src/cmd/go/env.go ファイルの mkEnv 関数内で行われています。

--- a/src/cmd/go/env.go
+++ b/src/cmd/go/env.go
@@ -6,6 +6,7 @@ package main
 
  import (
  	"fmt"
+	"os"
  	"runtime"
  	"strings"
  )
@@ -33,16 +34,17 @@ func mkEnv() []envVar {
  	b.init()
 
  	env := []envVar{
-		{"GOROOT", goroot},\n-		{"GOBIN", gobin},\n \t\t{\"GOARCH\", goarch},\n+\t\t{\"GOBIN", gobin},\n \t\t{\"GOCHAR", archChar},\n-		{"GOOS", goos},\n \t\t{\"GOEXE", exeSuffix},\n+\t\t{\"GOGCCFLAGS", strings.Join(b.gccCmd(\".\")[3:], \" \")},\n \t\t{\"GOHOSTARCH", runtime.GOARCH},\n \t\t{\"GOHOSTOS", runtime.GOOS},\n+\t\t{\"GOOS", goos},\n+\t\t{\"GOPATH", os.Getenv(\"GOPATH\")},\n+\t\t{\"GOROOT", goroot},\n \t\t{\"GOTOOLDIR", toolDir},\n-		{"GOGCCFLAGS", strings.Join(b.gccCmd(\".\")[3:], \" \")},\n \t}\n \n  	if buildContext.CgoEnabled {

具体的には、以下の変更が行われています。

  1. import "os" の追加: os.Getenv 関数を使用するために、os パッケージがインポートされています。
  2. env スライスの初期化部分の変更:
    • {"GOROOT", goroot}{"GOBIN", gobin} の初期位置が変更されています。
    • {"GOOS", goos}{"GOGCCFLAGS", strings.Join(b.gccCmd(".")[3:], " ")} の位置も変更されています。
    • 新たに {"GOPATH", os.Getenv("GOPATH")} が追加され、GOPATH の値が環境変数から取得されてリストに含まれるようになっています。
    • 全体として、環境変数の定義順序がアルファベット順に近くなるように再編成されています。

コアとなるコードの解説

このコミットの核心は、src/cmd/go/env.go 内の mkEnv 関数における env スライスの初期化部分です。

	env := []envVar{
		{"GOARCH", goarch},
		{"GOBIN", gobin},
		{"GOCHAR", archChar},
		{"GOEXE", exeSuffix},
		{"GOGCCFLAGS", strings.Join(b.gccCmd(".")[3:], " ")},
		{"GOHOSTARCH", runtime.GOARCH},
		{"GOHOSTOS", runtime.GOOS},
		{"GOOS", goos},
		{"GOPATH", os.Getenv("GOPATH")}, // ここでGOPATHが追加される
		{"GOROOT", goroot},
		{"GOTOOLDIR", toolDir},
	}
  • import "os": Goの標準ライブラリである os パッケージをインポートしています。このパッケージは、オペレーティングシステムとのインタラクション(環境変数の読み取り、ファイル操作など)を提供します。
  • {"GOPATH", os.Getenv("GOPATH")}: この行が GOPATHgo env の出力に追加する主要な変更です。
    • "GOPATH": これは環境変数名を示す文字列リテラルです。
    • os.Getenv("GOPATH"): os.Getenv 関数は、引数で指定された環境変数の値を取得します。ここではシステムに設定されている GOPATH の値が取得されます。もし GOPATH が設定されていない場合、この関数は空文字列を返します。
  • 環境変数リストのソート: 以前は GOROOT がリストの先頭にありましたが、この変更により、GOARCHGOBIN などが先にくるように順序が調整されています。これは、go env の出力がより予測可能で、アルファベット順に近い形になるようにするためのものです。これにより、ユーザーは特定の環境変数をより簡単に見つけられるようになります。

このシンプルな変更により、go env コマンドの利便性が大幅に向上し、Go開発者が環境設定をデバッグする際の効率が改善されました。

関連リンク

参考にした情報源リンク