[インデックス 13499] ファイルの概要
このコミットは、Go言語のドキュメンテーションツールである godoc
コマンドから -path
フラグを削除する変更です。これにより、godoc
がパッケージを探索する方法が簡素化され、GOROOT
および GOPATH
環境変数に依存する標準的なメカニズムに統一されます。
コミット
commit fba47dc3b10e7649e3ad0129b357d83cc2db228e
Author: Dave Cheney <dave@cheney.net>
Date: Wed Jul 25 10:49:50 2012 -0700
cmd/godoc: delete -path flag
Fixes #3453.
R=golang-dev, gri, jeff, bradfitz
CC=golang-dev
https://golang.org/cl/6350086
---
src/cmd/godoc/doc.go | 18 ++----------------
src/cmd/godoc/godoc.go | 11 -----------
2 files changed, 2 insertions(+), 27 deletions(-)
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/fba47dc3b10e7649e3ad0129b357d83cc2db228e
元コミット内容
cmd/godoc: delete -path flag
このコミットは、godoc
コマンドラインツールから -path
フラグを削除します。
関連するIssue: #3453 を修正します。
変更の背景
この変更の背景には、Go言語のパッケージ管理とツールの設計思想があります。Go言語では、ソースコードの場所を特定するために GOROOT
と GOPATH
という環境変数を主要なメカニズムとして使用します。
godoc
はGoのソースコードからドキュメントを生成し、表示するツールですが、かつては -path
フラグを通じて、GOROOT
や GOPATH
以外の追加のディレクトリをパッケージの探索パスとして指定できる機能がありました。
Issue #3453 (godoc: -path flag is confusing and unnecessary) では、この -path
フラグが以下の理由で問題視されていました。
- 混乱を招く:
GOROOT
やGOPATH
といった標準的なGoの環境設定メカニズムがあるにもかかわらず、godoc
固有の-path
フラグが存在することで、ユーザーがどのパス設定を使用すべきか混乱を招いていました。 - 冗長性: ほとんどの場合、
GOPATH
を適切に設定すれば、godoc
が必要なパッケージを見つけることができました。-path
フラグは、GOPATH
の概念と重複し、不必要な複雑さを加えていました。 - 一貫性の欠如: Goのエコシステム全体で
GOPATH
が標準的なワークスペースの概念として確立されつつあったため、特定のツールが独自のパス設定メカニズムを持つことは、一貫性を損なうと考えられました。
これらの理由から、godoc
のインターフェースを簡素化し、Goの標準的なパッケージ探索メカニズムに統一するために、-path
フラグの削除が決定されました。これにより、ユーザーは godoc
を含むGoツール群全体で GOROOT
と GOPATH
の設定に集中できるようになります。
前提知識の解説
このコミットを理解するためには、以下のGo言語の基本的な概念とツールの知識が必要です。
-
godoc
コマンド:godoc
はGo言語の公式ドキュメンテーションツールです。Goのソースコード(.go
ファイル)内のコメントや宣言から自動的にドキュメントを生成し、コマンドラインで表示したり、HTTPサーバーとして提供したりできます。- 開発者がコードを書く際に、Goの標準的なコメント規約に従うことで、自動的に高品質なドキュメントが生成される仕組みを提供します。
- Goの標準ライブラリのドキュメントも
godoc
によって生成され、pkg.go.dev (旧 golang.org/pkg/) で公開されています。
-
GOROOT
環境変数:GOROOT
はGoのインストールディレクトリを指す環境変数です。Goのコンパイラ、標準ライブラリのソースコード、ツールなどがこのディレクトリに格納されています。godoc
はデフォルトでGOROOT
内のパッケージを探索し、ドキュメントを生成します。
-
GOPATH
環境変数:GOPATH
はGoのワークスペースディレクトリを指す環境変数です。Go 1.11以降のGo Modulesの導入によりその重要性は薄れましたが、このコミットが作成された2012年当時は、ユーザーが開発するGoプロジェクトのソースコード、コンパイルされたバイナリ、パッケージの依存関係などがこのディレクトリ構造内に配置されるのが一般的でした。GOPATH
は通常、複数のディレクトリパスをコロン(Unix/Linux)またはセミコロン(Windows)で区切って指定できます。godoc
はGOPATH
内の各ディレクトリも探索対象とします。
-
Goのパッケージ探索メカニズム:
- Goのツール(
go build
,go install
,godoc
など)は、インポートパスに基づいてパッケージのソースコードを探索します。 - 探索は通常、
GOROOT/src
およびGOPATH/src
の下で行われます。例えば、import "fmt"
であればGOROOT/src/fmt
を、import "github.com/user/repo"
であればGOPATH/src/github.com/user/repo
を探します。
- Goのツール(
-
flag
パッケージ:- Goの標準ライブラリに含まれる
flag
パッケージは、コマンドライン引数を解析するための機能を提供します。 flag.String
,flag.Int
などの関数を使って、コマンドラインフラグとそのデフォルト値、説明を定義します。
- Goの標準ライブラリに含まれる
-
filepath
パッケージ:- Goの標準ライブラリに含まれる
filepath
パッケージは、ファイルパスの操作(結合、分割、クリーンアップなど)を行うための機能を提供します。 filepath.SplitList
は、OS固有のパス区切り文字(例::
や;
)で区切られたパス文字列を個々のパスのリストに分割します。
- Goの標準ライブラリに含まれる
-
fs.Bind
(godoc内部のファイルシステム抽象化):godoc
は、実際のファイルシステムを直接操作するのではなく、抽象化されたファイルシステム (fs
パッケージ) を使用しています。これにより、ファイルシステムをメモリ上にマウントしたり、ZIPファイルから読み込んだりするなどの柔軟な操作が可能になります。fs.Bind
は、特定のパスを別のファイルシステム(またはファイルシステム内の別のパス)に「バインド」(マウント)する機能を提供します。これにより、godoc
は複数の異なる場所にあるソースコードをあたかも単一の仮想ファイルシステム内にあるかのように扱うことができます。
技術的詳細
このコミットは、godoc
コマンドの -path
フラグに関連するコードとドキュメントを完全に削除することで、その機能を廃止しています。
具体的には、以下の2つのファイルが変更されています。
-
src/cmd/godoc/doc.go
:- このファイルは
godoc
コマンドのヘルプメッセージやドキュメンテーションを定義しています。 - 変更前は、
-path
フラグの説明(追加のパッケージディレクトリを指定する方法、コロン区切り、絶対パスからパッケージパスへのマッピング例など)が詳細に記述されていました。 - 変更後は、これらの
-path
フラグに関する説明がすべて削除されています。 - また、「By default, godoc looks at the packages it finds via $GOROOT and $GOPATH (if set).」という記述に続き、変更前は「Additional directories may be specified via the -path flag...」とあった部分が、変更後には「This behavior can be altered by providing an alternative $GOROOT with the -goroot flag.」と変更され、
GOROOT
のみでパス設定を変更できる旨が強調されています。
- このファイルは
-
src/cmd/godoc/godoc.go
:- このファイルは
godoc
コマンドの主要なロジックを含んでいます。 - 変更前は、
flag.String("path", "", "additional package directories (colon-separated)")
という行でpkgPath
という名前のコマンドラインフラグが定義されていました。これが-path
フラグの実体です。この定義が削除されました。 - さらに重要な変更として、
initHandlers
関数内の、pkgPath
フラグの値に基づいて追加のディレクトリをgodoc
の仮想ファイルシステムにバインドするロジックが完全に削除されました。- このロジックは、
filepath.SplitList(*pkgPath)
を使って-path
で指定されたパスリストを分割し、それぞれのパスをfs.Bind("/src/pkg/"+elem, OS(p), "/", bindReplace)
の形式でgodoc
の内部ファイルシステムにマウントしていました。 - この
fs.Bind
の呼び出しは、指定された外部ディレクトリをgodoc
が認識する/src/pkg/
以下の仮想パスにマッピングする役割を担っていました。このコードブロックが削除されたことで、-path
フラグによる外部ディレクトリの追加機能が完全に失われました。
- このロジックは、
- このファイルは
この変更により、godoc
は GOROOT
と GOPATH
(およびGo Modulesが有効な場合はモジュールキャッシュ) のみに依存してパッケージを探索するようになり、パス解決のロジックが簡素化され、Goのエコシステム全体での一貫性が向上しました。
コアとなるコードの変更箇所
src/cmd/godoc/doc.go
の変更
--- a/src/cmd/godoc/doc.go
+++ b/src/cmd/godoc/doc.go
@@ -67,8 +67,6 @@ The flags are:
-maxresults=10000
\tmaximum number of full text search results shown
\t(no full text index is built if maxresults <= 0)
-- -path=""
-- \t\tadditional package directories (colon-separated)
-html
\t\tprint HTML in command-line mode
-goroot=$GOROOT
@@ -88,20 +86,8 @@ The flags are:
\tzip file providing the file system to serve; disabled if empty
By default, godoc looks at the packages it finds via $GOROOT and $GOPATH (if set).
-Additional directories may be specified via the -path flag which accepts a list
-of colon-separated paths; unrooted paths are relative to the current working
-directory. Each path is considered as an additional root for packages in order
-of appearance. The last (absolute) path element is the prefix for the package
-path. For instance, given the flag value:
-
- path=".:/home/bar:/public"
-
-for a godoc started in /home/user/godoc, absolute paths are mapped to package paths
-as follows:
-
- /home/user/godoc/x -> godoc/x
- /home/bar/x -> bar/x
- /public/x -> public/x
+This behavior can be altered by providing an alternative $GOROOT with the -goroot
+flag.
When godoc runs as a web server and -index is set, a search index is maintained.
The index is created at startup.
src/cmd/godoc/godoc.go
の変更
--- a/src/cmd/godoc/godoc.go
+++ b/src/cmd/godoc/godoc.go
@@ -57,7 +57,6 @@ var (
// TODO(gri) consider the invariant that goroot always end in '/'
goroot = flag.String("goroot", runtime.GOROOT(), "Go root directory")
testDir = flag.String("testdir", "", "Go root subdirectory - for testing only (faster startups)")
-- pkgPath = flag.String("path", "", "additional package directories (colon-separated)")
// layout control
tabwidth = flag.Int("tabwidth", 4, "tab width")
@@ -83,16 +82,6 @@ var (
)
func initHandlers() {
-- // Add named directories in -path argument as
-- // subdirectories of src/pkg.
-- for _, p := range filepath.SplitList(*pkgPath) {
-- _, elem := filepath.Split(p)
-- if elem == "" {
-- log.Fatalf("invalid -path argument: %q has no final element", p)
-- }
-- fs.Bind("/src/pkg/"+elem, OS(p), "/", bindReplace)
-- }
--
fileServer = http.FileServer(&httpFS{fs})\n \tcmdHandler = docServer{"/cmd/", "/src/cmd", false}\n \tpkgHandler = docServer{"/pkg/", "/src/pkg", true}\n```
## コアとなるコードの解説
### `src/cmd/godoc/doc.go` の変更点
このファイルは `godoc` コマンドのユーザー向けドキュメントを定義しています。
* `-path` フラグに関する説明のブロック全体が削除されています。これには、フラグの目的、パスの指定方法、そして絶対パスがどのように `godoc` の内部的なパッケージパスにマッピングされるかの詳細な例が含まれていました。この削除は、ユーザーがこのフラグを使用できなくなることを明確に示しています。
* `godoc` がパッケージを探索するデフォルトの動作に関する説明が更新されています。以前は `GOROOT` と `GOPATH` に加えて `-path` フラグで追加ディレクトリを指定できると説明されていましたが、変更後は `-goroot` フラグを使って `GOROOT` を変更することでこの動作を調整できる、という説明に簡素化されています。これは、`godoc` のパス解決が `GOROOT` と `GOPATH` に集約されたことを反映しています。
### `src/cmd/godoc/godoc.go` の変更点
このファイルは `godoc` コマンドの実際のロジックを実装しています。
* **フラグ定義の削除**:
```diff
- pkgPath = flag.String("path", "", "additional package directories (colon-separated)")
```
この行は、`godoc` がコマンドライン引数として `-path` フラグを認識し、その値を `pkgPath` 変数に格納するための定義でした。この行が削除されたことで、`godoc` はもはや `-path` フラグを有効な引数として認識しなくなります。
* **パスバインディングロジックの削除**:
```diff
- // Add named directories in -path argument as
- // subdirectories of src/pkg.
- for _, p := range filepath.SplitList(*pkgPath) {
- _, elem := filepath.Split(p)
- if elem == "" {
- log.Fatalf("invalid -path argument: %q has no final element", p)
- }
- fs.Bind("/src/pkg/"+elem, OS(p), "/", bindReplace)
- }
```
このコードブロックは `initHandlers` 関数内にあり、`godoc` がHTTPリクエストを処理する前に初期設定を行う部分です。
* `filepath.SplitList(*pkgPath)`: `-path` フラグで指定されたコロン区切りのパス文字列を個々のパスに分割していました。
* `for` ループ: 分割された各パス `p` に対して処理を行っていました。
* `filepath.Split(p)`: パス `p` をディレクトリ部分と最後の要素(ファイル名またはディレクトリ名)に分割していました。ここで取得される `elem` が、`godoc` の仮想ファイルシステム内でパッケージパスのプレフィックスとして使用されていました。
* `log.Fatalf(...)`: 無効なパス(最後の要素がない場合)に対するエラーハンドリングです。
* `fs.Bind("/src/pkg/"+elem, OS(p), "/", bindReplace)`: これが最も重要な部分です。`fs.Bind` は `godoc` 内部の抽象化されたファイルシステム (`fs`) に対して、指定された物理パス `OS(p)` を、`godoc` が認識する仮想パス `/src/pkg/` の下にマウントする役割を担っていました。例えば、`-path=/home/user/mycode` と指定すると、`/home/user/mycode` の内容が `godoc` の内部では `/src/pkg/mycode` として扱われ、`mycode/mypackage` のようなパッケージが `godoc` で参照可能になっていました。
このコードブロック全体が削除されたことで、`godoc` は外部から指定された追加のディレクトリをパッケージソースとして認識するメカニズムを完全に失いました。これにより、`godoc` のパッケージ探索は `GOROOT` と `GOPATH` の標準的なルールに厳密に従うことになります。
## 関連リンク
* Go Issue #3453: [godoc: -path flag is confusing and unnecessary](https://github.com/golang/go/issues/3453)
* Go言語の公式ドキュメント: [https://go.dev/doc/](https://go.dev/doc/)
* `godoc` コマンドの現在のドキュメント (Goのバージョンによって内容は異なります): `go doc cmd/godoc` または [https://pkg.go.dev/cmd/godoc](https://pkg.go.dev/cmd/godoc)
## 参考にした情報源リンク
* GitHubのコミットページ: [https://github.com/golang/go/commit/fba47dc3b10e7649e3ad0129b357d83cc2db228e](https://github.com/golang/go/commit/fba47dc3b10e7649e3ad0129b357d83cc2db228e)
* Go Issue #3453: [https://github.com/golang/go/issues/3453](https://github.com/golang/go/issues/3453)
* Go言語の環境変数 `GOROOT` と `GOPATH` に関する情報 (Go Modules導入以前の文脈も含む):
* [https://go.dev/doc/code](https://go.dev/doc/code) (Go Modules導入後の現在のドキュメント)
* 古いGoのドキュメントやブログ記事 (例: Go 1.0, Go 1.1, Go 1.2 リリースノートなど)
* Goの `flag` パッケージのドキュメント: [https://pkg.go.dev/flag](https://pkg.go.dev/flag)
* Goの `path/filepath` パッケージのドキュメント: [https://pkg.go.dev/path/filepath](https://pkg.go.dev/path/filepath)
* Goの `log` パッケージのドキュメント: [https://pkg.go.dev/log](https://pkg.go.dev/log)
* Goの `net/http` パッケージのドキュメント: [https://pkg.go.dev/net/http](https://pkg.go.dev/net/http)
* Goの `runtime` パッケージのドキュメント: [https://pkg.go.dev/runtime](https://pkg.go.dev/runtime)
* `godoc` の内部実装に関する情報 (Goのソースコード): [https://github.com/golang/go/tree/master/src/cmd/godoc](https://github.com/golang/go/tree/master/src/cmd/godoc)
* Gerrit Change-Id: [https://golang.org/cl/6350086](https://golang.org/cl/6350086) (GoプロジェクトがGerritを使用していた時期の変更履歴)