[インデックス 11837] ファイルの概要
このコミットは、Go言語のcmd/fix
ツールに、非推奨となったパッケージ(exp
、old
、deleted
に分類されるパッケージ)の使用に対して警告を発する機能を追加するものです。これにより、Go 1のリリースに伴うパッケージの整理と移行を開発者がよりスムーズに行えるよう支援します。
コミット
commit 878153682ecac3fb00bdad50ff8dcc296e30a701
Author: Russ Cox <rsc@golang.org>
Date: Sun Feb 12 23:55:33 2012 -0500
cmd/fix: warn about exp, old, deleted packages
Fixes #2776.
There was a previous attempt at CL 5592043 but that
seems to have stalled. This one is simpler, and more up to date
(correct handling of spdy, for example).
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5645091
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/878153682ecac3fb00bdad50ff8dcc296e30a701
元コミット内容
cmd/fix
: exp
、old
、deleted
パッケージについて警告する
Issue #2776 を修正。
以前にCL 5592043で試みられたが、それは停滞しているようだ。 今回のものはよりシンプルで、より最新の状態に対応している(例えば、spdyの正しい扱いなど)。
R=golang-dev, r CC=golang-dev https://golang.org/cl/5645091
変更の背景
このコミットは、Go言語の最初の安定版リリースであるGo 1の準備段階で行われました。Go 1では、標準ライブラリのAPI安定化と整理が重要な目標の一つでした。これに伴い、一部のパッケージは標準ライブラリから削除されたり、別のリポジトリに移動されたり、あるいは実験的な(exp
)状態のまま残されたりしました。
このような変更は、既存のGoプログラムがGo 1に移行する際に、互換性の問題を引き起こす可能性があります。特に、削除されたパッケージや移動されたパッケージを使用しているコードは、手動での修正が必要になります。go fix
ツールは、Goのバージョンアップに伴うコードの自動修正を支援するために設計されていますが、Go 1のリリース時点では、これらの非推奨パッケージの使用に対する警告機能が不足していました。
コミットメッセージにある「Fixes #2776」は、この問題がGoのIssueトラッカーで追跡されていたことを示しています。Issue #2776は、go fix
が削除されたパッケージやexp
パッケージの使用について警告すべきであるという要望でした。このコミットは、その要望に応える形で、開発者がGo 1への移行時に自身のコードベースで非推奨パッケージの使用箇所を特定し、修正するのを助けることを目的としています。
以前にも同様の試み(CL 5592043)があったものの、それが停滞していたため、よりシンプルで最新の状況(特にspdy
パッケージの扱い)に対応した新しい実装が提案されました。
前提知識の解説
Go言語のgo fix
コマンド
go fix
コマンドは、Go言語のツールチェーンの一部であり、Goの新しいバージョンへの移行に伴うコードの自動修正を支援するために使用されます。Go言語は後方互換性を重視していますが、言語仕様や標準ライブラリの変更によって、古いコードが新しいバージョンでコンパイルできなくなったり、意図しない動作をしたりする場合があります。go fix
は、このような互換性の問題を自動的に検出し、修正する機能を提供します。例えば、パッケージ名の変更やAPIの変更に対応するために、インポートパスや関数呼び出しを自動的に書き換えることができます。
Go 1リリースとパッケージの整理
Go 1は、Go言語の最初の安定版リリースであり、言語仕様と標準ライブラリのAPIが安定化されました。これにより、Go 1で書かれたプログラムは、将来のGoのバージョンでも動作することが保証されるようになりました。この安定化の過程で、標準ライブラリに含まれていた一部のパッケージが整理されました。
exp
パッケージ:exp
(experimental)は、実験的なパッケージを含むディレクトリです。これらのパッケージは、将来的に標準ライブラリに取り込まれる可能性がありますが、APIが安定しておらず、変更される可能性があります。Go 1の時点では、exp
内のパッケージは標準ライブラリの一部とは見なされず、使用は推奨されませんでした。old
パッケージ:old
は、Goの初期バージョンで存在したが、Go 1で非推奨または削除されたパッケージを含むディレクトリです。これらのパッケージは、Go 1では使用すべきではありません。deleted
パッケージ: Go 1で完全に削除されたパッケージです。これらのパッケージは、もはやGoの標準配布物には含まれていません。
これらのパッケージの整理は、標準ライブラリの品質と保守性を向上させるための重要なステップでしたが、既存のコードベースを持つ開発者にとっては移行の課題となりました。
GoのIssueトラッカーとChange List (CL)
- Issueトラッカー: Goプロジェクトは、バグ報告や機能要望を追跡するためにIssueトラッカー(当時はGoogle CodeのIssueトラッカー、現在はGitHub Issues)を使用しています。Issue #2776は、
go fix
が非推奨パッケージについて警告すべきであるという具体的な要望でした。 - Change List (CL): Goプロジェクトでは、コード変更はChange List (CL) として提出され、レビュープロセスを経てマージされます。コミットメッセージにある
CL 5592043
やCL 5645091
は、これらの変更提案を指します。
技術的詳細
このコミットの主要な技術的変更は、src/cmd/fix/go1pkgrename.go
ファイルに集中しています。このファイルは、Go 1への移行に伴うパッケージのリネームを処理するgo fix
のロジックを含んでいます。
変更の核心は、go1PackageRenames
という構造体スライスに、exp
、old
、deleted
に分類されるパッケージのエントリを追加したことです。
exp
パッケージの追加:ebnf
やgo/types
といったパッケージがexp/ebnf
やexp/types
としてリストに追加されました。これらの新しいパスは、exp/
プレフィックスを持つことで、実験的なパッケージであることを示します。deleted
パッケージの追加:container/vector
、exp/datafmt
、go/typechecker
、old/netchan
、old/regexp
、old/template
、try
といったパッケージが、新しいパスが空文字列(""
)としてリストに追加されました。これは、これらのパッケージが完全に削除されたことを示します。
go1pkgrename
関数内のロジックが修正され、これらの新しいエントリを処理するようになりました。
- インポートのチェック:
importSpec
関数(既存のimports
関数の代わりに導入された、より詳細な情報を提供する関数)を使用して、ファイルが特定の古いパッケージをインポートしているかどうかをチェックします。 - 削除されたパッケージの警告:
rename.new
が空文字列(""
)の場合、そのパッケージがGo 1で削除されたことを意味します。この場合、warn
関数が呼び出され、「package %q has been deleted in Go 1」(パッケージ %q はGo 1で削除されました)という警告メッセージが表示されます。 exp
パッケージの警告:rename.new
がexp/
で始まる場合、そのパッケージがGo 1の一部ではないことを意味します。この場合も、warn
関数が呼び出され、「package %q is not part of Go 1」(パッケージ %q はGo 1の一部ではありません)という警告メッセージが表示されます。- パッケージのリネーム: 削除されたパッケージや
exp
パッケージでない場合、既存のrewriteImport
関数が呼び出され、パッケージのインポートパスが新しいパスに書き換えられます。
この変更により、go fix
は単にパッケージをリネームするだけでなく、非推奨または削除されたパッケージの使用を検出し、開発者に適切な警告を出すことができるようになりました。これにより、開発者はGo 1への移行時に、自身のコードベースで修正が必要な箇所をより簡単に特定できるようになります。
また、doc/go1.html
とdoc/go1.tmpl
から、以前の「TODO: go fix should warn about deletions.」のようなコメントが削除されています。これは、このコミットによってそのTODOが完了したことを示しています。
コアとなるコードの変更箇所
src/cmd/fix/go1pkgrename.go
このファイルは、go fix
コマンドがGo 1のパッケージリネームを処理するためのロジックを含んでいます。
--- a/src/cmd/fix/go1pkgrename.go
+++ b/src/cmd/fix/go1pkgrename.go
@@ -6,6 +6,7 @@ package main
import (
"go/ast"
+ "strings"
)
func init() {
@@ -76,10 +77,24 @@ var go1PackageRenames = []struct{ old, new string }{\
{"net/dict", "code.google.com/p/go.net/dict"},
{"net/websocket", "code.google.com/p/go.net/websocket"},
{"exp/spdy", "code.google.com/p/go.net/spdy"},
+ {"http/spdy", "code.google.com/p/go.net/spdy"},
// go.codereview sub-repository
{"encoding/git85", "code.google.com/p/go.codereview/git85"},
{"patch", "code.google.com/p/go.codereview/patch"},
+
+ // exp
+ {"ebnf", "exp/ebnf"},
+ {"go/types", "exp/types"},
+
+ // deleted
+ {"container/vector", ""},
+ {"exp/datafmt", ""},
+ {"go/typechecker", ""},
+ {"old/netchan", ""},
+ {"old/regexp", ""},
+ {"old/template", ""},
+ {"try", ""},
}
var go1PackageNameRenames = []struct{ newPath, old, new string }{
@@ -92,12 +107,20 @@ func go1pkgrename(f *ast.File) bool {
// First update the imports.
for _, rename := range go1PackageRenames {
- if !imports(f, rename.old) {
+ spec := importSpec(f, rename.old)
+ if spec == nil {
continue
}
+ if rename.new == "" {
+ warn(spec.Pos(), "package %q has been deleted in Go 1", rename.old)
+ continue
+ }
if rewriteImport(f, rename.old, rename.new) {
fixed = true
}
+ if strings.HasPrefix(rename.new, "exp/") {
+ warn(spec.Pos(), "package %q is not part of Go 1", rename.new)
+ }
}
if !fixed {
return false
src/cmd/fix/go1pkgrename_test.go
このファイルは、go1pkgrename
関数のテストケースを含んでいます。
--- a/src/cmd/fix/go1pkgrename_test.go
+++ b/src/cmd/fix/go1pkgrename_test.go
@@ -87,6 +87,11 @@ import (
import "cmath"
import poot "exp/template/html"
+import (
+ "ebnf"
+ "old/regexp"
+)
+
var _ = cmath.Sin
var _ = poot.Poot
`,
@@ -95,6 +100,11 @@ var _ = poot.Poot
import "math/cmplx"
import poot "html/template"
+import (
+ "exp/ebnf"
+ "old/regexp"
+)
+
var _ = cmplx.Sin
var _ = poot.Poot
`,
doc/go1.html
および doc/go1.tmpl
これらのファイルはGo 1のリリースノートのドキュメントであり、go fix
が非推奨パッケージについて警告すべきであるというTODOコメントが削除されています。
--- a/doc/go1.html
+++ b/doc/go1.html
@@ -539,8 +539,6 @@ Running <code>go fix</code> will update all imports and package renames for pack
remain inside the standard repository. Programs that import packages
that are no longer in the standard repository will need to be edited
by hand.
-<br>
-<font color="red">TODO: go fix should warn about deletions.</font>
</p>
<h3 id="exp">The package tree exp</h3>
@@ -581,8 +579,6 @@ If they are installed, they now reside in <code>$GOROOT/bin/tool</code>.
Code that uses packages in <code>exp</code> will need to be updated by hand,
or else compiled from an installation that has <code>exp</code> available.
The go fix tool or the compiler will complain about such uses.
-<br>
-<font color="red">TODO: go fix should warn about such uses.</font>
</p>
<h3 id="old">The package tree old</h3>
@@ -608,8 +604,6 @@ The packages in their new locations are:
Code that uses packages now in <code>old</code> will need to be updated by hand,
or else compiled from an installation that has <code>old</code> available.
The go fix tool will warn about such uses.
-<br>
-<font color="red">TODO: go fix should warn about such uses.</font>
</p>
<h3 id="deleted">Deleted packages</h3>
@@ -636,8 +630,6 @@ slices directly. See
<a href="http://code.google.com/p/go-wiki/wiki/SliceTricks">the Go
Language Community Wiki</a> for some suggestions.
Code that uses the other packages (there should be almost zero) will need to be rethought.
-<br>
-<font color="red">TODO: go fix should warn such uses.</font>
</p>
<h3 id="subrepo">Packages moving to subrepositories</h3>
コアとなるコードの解説
go1pkgrename.go
の変更点
-
import "strings"
の追加:strings.HasPrefix
関数を使用するために、strings
パッケージがインポートされました。これは、exp/
プレフィックスを持つパッケージを識別するために使用されます。 -
go1PackageRenames
構造体スライスの拡張: このスライスは、Go 1で変更されたパッケージのマッピングを定義します。exp
パッケージ(例:ebnf
->exp/ebnf
)と、新しいパスがexp/
で始まるエントリが追加されました。deleted
パッケージ(例:container/vector
->""
)と、新しいパスが空文字列のエントリが追加されました。空文字列は、そのパッケージが削除されたことを示すマーカーとして機能します。http/spdy
からcode.google.com/p/go.net/spdy
へのリネームも追加されており、これはコミットメッセージにある「correct handling of spdy」に対応します。
-
go1pkgrename
関数のロジック変更:imports(f, rename.old)
の代わりにspec := importSpec(f, rename.old)
が使用されるようになりました。importSpec
は、単にインポートが存在するかどうかをチェックするだけでなく、そのインポートのASTノード(*ast.ImportSpec
)を返します。これにより、警告メッセージで正確な位置情報(spec.Pos()
)を提供できるようになります。- 削除されたパッケージの警告ロジック:
if rename.new == "" { warn(spec.Pos(), "package %q has been deleted in Go 1", rename.old) continue }
go1PackageRenames
でnew
フィールドが空文字列に設定されている場合、そのパッケージはGo 1で削除されたと見なされます。go fix
は、そのインポートが存在するコード行に対して、「package %q has been deleted in Go 1」という警告を出力します。continue
により、このインポートに対するさらなる処理(リネームなど)はスキップされます。 exp
パッケージの警告ロジック:if strings.HasPrefix(rename.new, "exp/") { warn(spec.Pos(), "package %q is not part of Go 1", rename.new) }
go1PackageRenames
でnew
フィールドがexp/
で始まる場合、そのパッケージはGo 1の標準ライブラリの一部ではないと見なされます。go fix
は、そのインポートが存在するコード行に対して、「package %q is not part of Go 1」という警告を出力します。この警告は、パッケージがリネームされた後(rewriteImport
が実行された後)に表示されるため、開発者は新しいexp/
パスを使用しているにもかかわらず、それが実験的なパッケージであることを認識できます。
go1pkgrename_test.go
の変更点
テストファイルには、ebnf
とold/regexp
のインポートを含む新しいテストケースが追加されました。これにより、go fix
がこれらの非推奨パッケージを正しく検出し、警告を生成するかどうかを確認できます。テストの期待される出力には、これらのパッケージがそれぞれexp/ebnf
とold/regexp
にリネームされることが含まれていますが、同時に警告も発生することが暗黙的にテストされます。
ドキュメントファイルの変更点
doc/go1.html
とdoc/go1.tmpl
から、go fix
が削除されたパッケージやexp
パッケージについて警告すべきであるというTODOコメントが削除されました。これは、このコミットによってこれらの機能が実装され、TODOが完了したことを示しています。
これらの変更により、go fix
はGo 1への移行プロセスにおいて、開発者にとってより強力で役立つツールとなりました。
関連リンク
- Go Issue 2776:
cmd/fix
: warn about exp, old, deleted packages - https://github.com/golang/go/issues/2776 (このコミットが修正したIssue) - Go 1 Release Notes (Go 1の公式リリースノート。パッケージの整理に関する情報が含まれているはずです) - https://go.dev/doc/go1
go fix
command documentation (Goの公式ドキュメントにおけるgo fix
コマンドの説明) - https://go.dev/cmd/go/#hdr-Fix_packages
参考にした情報源リンク
- https://github.com/golang/go/commit/878153682ecac3fb00bdad50ff8dcc296e30a701 (このコミットのGitHubページ)
- https://go.dev/doc/go1 (Go 1リリースノート)
- https://go.dev/cmd/go/#hdr-Fix_packages (
go fix
コマンドのドキュメント) - https://github.com/golang/go/issues/2776 (Go Issue 2776)
- Go言語の
exp
パッケージに関する一般的な情報 (例: Goのブログ記事やコミュニティの議論など、具体的なURLは検索結果による) - Go言語の
old
パッケージに関する一般的な情報 (例: Goのブログ記事やコミュニティの議論など、具体的なURLは検索結果による) - Go言語のパッケージ管理とモジュールに関する一般的な情報 (Go Modules登場以前のGoのパッケージ管理の概念)