[インデックス 10200] ファイルの概要
このコミットは、Go言語のコンパイラ(gc
)において、以前追加された実験的な機能であるGOEXPERIMENT=os.Error
を元に戻すものです。この機能は、os.Error
をerror
型へのエイリアスとして定義するものでしたが、コミットメッセージにある通り、短期間で削除されることが約束されていました。
コミット
commit 4c3ea0008c81e18688fc77f73dd0a8bb0c8ad323
Author: Russ Cox <rsc@golang.org>
Date: Tue Nov 1 23:26:10 2011 -0400
undo CL 5330066 / 6a5647d82728
I promised it wouldn't last very long.
People who really need this can sync to 6a5647d82728.
««« original CL description
gc: add GOEXPERIMENT=os.Error
This won't last long, I promise.
R=ken2
CC=golang-dev
https://golang.org/cl/5330066
»»»
R=ken2
CC=golang-dev
https://golang.org/cl/5333053
---
src/cmd/gc/go.h | 1 -
src/cmd/gc/lex.c | 1 -
src/cmd/gc/subr.c | 11 -----------
3 files changed, 13 deletions(-)
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index cff01a11f8..7d6ac08433 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -852,7 +852,6 @@ EXTERN int typecheckok;
EXTERN int compiling_runtime;
EXTERN int rune32;
-EXTERN int oserror;
/*
*\ty.tab.c
diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c
index 1dc00d70d3..86492a53bc 100644
--- a/src/cmd/gc/lex.c
+++ b/src/cmd/gc/lex.c
@@ -38,7 +38,6 @@ static struct {
int *val;
} exper[] = {
{"rune32", &rune32},
-\t{"os.Error", &oserror},
};
static void
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index 1d5c1aad25..dc1d314638 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -2967,17 +2967,6 @@ mkpkg(Strlit *path)\n p->prefix = pathtoprefix(path->s);\n p->link = phash[h];\n phash[h] = p;\n-\t\n-\t// If the compiler was built with\n-\t//\tGOEXPERIMENT=os.Error\n-\t// define os.Error as an alias for error.\n-\t// Terrible and won\'t last long, but useful for transitions.\n-\tif(oserror && strcmp(path->s, \"os\") == 0) {\n-\t\tSym *s;\n-\t\ts = pkglookup(\"Error\", p);\n-\t\ts->def = typenod(errortype);\n-\t}\n-\n \treturn p;\n }\n \n```
## GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/4c3ea0008c81e18688fc77f73dd0a8bb0c8ad323
## 元コミット内容
このコミットは、以下の元のコミット(CL 5330066 / 6a5647d82728)を元に戻すものです。
gc: add GOEXPERIMENT=os.Error
This won't last long, I promise.
R=ken2 CC=golang-dev https://golang.org/cl/5330066
元のコミットは、Goコンパイラに`GOEXPERIMENT=os.Error`という実験的なフラグを追加するものでした。このフラグが有効な場合、`os.Error`という型が`error`型へのエイリアスとして定義されるようにコンパイラが振る舞うように変更されていました。コミットメッセージには「これは長くは続かないだろう、約束する」と明記されており、一時的な措置であることが示唆されていました。
## 変更の背景
このコミットの背景には、Go言語のエラーハンドリングの進化と、一時的な互換性レイヤーの必要性がありました。Go言語では、エラーは`error`インターフェースとして表現され、関数はエラーを戻り値として明示的に返すのが慣習です。しかし、初期のGo言語の設計段階や、特定のライブラリの移行期間において、`os`パッケージ内で`Error`という名前が使われていた時期があった可能性があります。
`GOEXPERIMENT=os.Error`は、おそらく`os.Error`という古い(あるいは提案されていた)型名から、現在の標準である`error`インターフェースへの移行を容易にするための一時的な措置として導入されました。開発者が既存のコードベースを`os.Error`から`error`に移行する際に、コンパイラレベルでのエイリアスを提供することで、段階的な移行を可能にする目的があったと考えられます。
しかし、このような実験的な機能は、言語の安定性や一貫性を保つために、最終的には削除されるべきものです。コミットメッセージにある「I promised it wouldn't last very long.」という言葉は、この機能が最初から一時的なものとして計画されており、その役割を終えたため削除されたことを明確に示しています。
## 前提知識の解説
### Go言語のエラーハンドリング
Go言語では、エラーは組み込みの`error`インターフェースによって表現されます。このインターフェースは、`Error() string`という単一のメソッドを持ち、エラーメッセージを文字列として返します。関数は通常、最後の戻り値として`error`型を返し、操作が成功した場合は`nil`を、失敗した場合は非`nil`のエラー値を返します。
```go
func doSomething() (result string, err error) {
// ... 処理 ...
if someCondition {
return "", errors.New("something went wrong")
}
return "success", nil
}
このシンプルで明示的なエラーハンドリングは、Go言語の設計思想の核となる部分です。
GOEXPERIMENT
とは
GOEXPERIMENT
は、Go言語のツールチェイン(コンパイラ、リンカなど)が持つ環境変数の一つです。これは、まだ安定版としてリリースされていない、実験的な機能や変更を有効にするために使用されます。GOEXPERIMENT
フラグは、新しい言語機能、コンパイラの最適化、ランタイムの変更などを、一般公開前にテストしたり、特定のユーザーが早期に試したりするために提供されます。
GOEXPERIMENT
で有効化される機能は、将来のGoのバージョンで正式に導入されることもあれば、破棄されることもあります。そのため、GOEXPERIMENT
は通常、開発者やGo言語の進化に深く関わる人々が使用するものであり、本番環境での使用は推奨されません。
os.Error
とerror
型
Go言語の標準ライブラリにはos
パッケージがあり、オペレーティングシステムとのインタラクション(ファイル操作、プロセス管理など)を提供します。このパッケージ内の関数は、エラーが発生した場合にerror
インターフェースを返します。
GOEXPERIMENT=os.Error
が有効な場合、コンパイラはos.Error
という名前をerror
型へのエイリアスとして扱っていました。これは、例えば以下のようなコードがコンパイル可能になることを意味します。
// GOEXPERIMENT=os.Error が有効な場合
var myErr os.Error = errors.New("test error")
通常、os.Error
という型はGo言語の標準ライブラリには存在しません。この実験的なエイリアスは、特定の移行期間中に、os.Error
という名前で書かれた既存のコードが、Go言語の標準的なerror
インターフェースに準拠した新しいコードと共存できるようにするためのものでした。
技術的詳細
このコミットは、GOEXPERIMENT=os.Error
という実験的な機能をGoコンパイラから削除するものです。具体的には、コンパイラのソースコードから、この実験フラグに関連する定義と処理を取り除いています。
GOEXPERIMENT
フラグは、コンパイラのビルド時に特定のコードパスを有効にするために使用されます。この場合、os.Error
フラグが有効であれば、コンパイラはos
パッケージ内でError
というシンボルを見つけた際に、それを組み込みのerror
型として扱うように内部的に設定されていました。
削除されたコードは、主に以下の3つのファイルに分散していました。
src/cmd/gc/go.h
: コンパイラのグローバルなヘッダーファイルで、oserror
という変数が宣言されていました。この変数は、GOEXPERIMENT=os.Error
が有効かどうかを示すフラグとして機能していました。src/cmd/gc/lex.c
: 字句解析器に関連するファイルで、GOEXPERIMENT
環境変数を解析し、対応する内部フラグ(oserror
など)を設定するロジックが含まれていました。"os.Error"
という文字列と&oserror
のペアが、実験フラグのリストから削除されています。src/cmd/gc/subr.c
: コンパイラのサブルーチンが含まれるファイルで、mkpkg
関数内にos.Error
をerror
型へのエイリアスとして定義する具体的なロジックが含まれていました。このロジックは、oserror
フラグが真であり、かつ現在のパッケージがos
パッケージである場合に、os.Error
シンボルをerrortype
(Goの組み込みerror
型)に解決するようにしていました。
この実験が短期間で終了した理由は、おそらく以下の点が挙げられます。
- 一時的な互換性レイヤーとしての役割の完了: 移行期間が終了し、
os.Error
という古い(または提案されていた)命名が不要になったため。 - 言語の一貫性の維持:
error
インターフェースがGo言語のエラーハンドリングの標準として確立されたため、特定のパッケージに限定されたエイリアスは混乱を招く可能性があった。 - コンパイラの複雑性の軽減: 実験的な機能を削除することで、コンパイラのコードベースをシンプルに保ち、メンテナンスコストを削減できる。
このコミットは、Go言語がその設計原則に忠実に、シンプルで一貫性のあるエラーハンドリングモデルを維持しようとする姿勢を示しています。
コアとなるコードの変更箇所
このコミットでは、以下の3つのファイルから合計13行が削除されています。
src/cmd/gc/go.h
: 1行削除src/cmd/gc/lex.c
: 1行削除src/cmd/gc/subr.c
: 11行削除
具体的な変更箇所は以下の通りです。
src/cmd/gc/go.h
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -852,7 +852,6 @@ EXTERN int typecheckok;
EXTERN int compiling_runtime;
EXTERN int rune32;
-EXTERN int oserror;
/*
*\ty.tab.c
src/cmd/gc/lex.c
--- a/src/cmd/gc/lex.c
+++ b/src/cmd/gc/lex.c
@@ -38,7 +38,6 @@ static struct {
int *val;
} exper[] = {
{"rune32", &rune32},
-\t{"os.Error", &oserror},
};
static void
src/cmd/gc/subr.c
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -2967,17 +2967,6 @@ mkpkg(Strlit *path)\n p->prefix = pathtoprefix(path->s);\n p->link = phash[h];\n phash[h] = p;\n-\t\n-\t// If the compiler was built with\n-\t//\tGOEXPERIMENT=os.Error\n-\t// define os.Error as an alias for error.\n-\t// Terrible and won\'t last long, but useful for transitions.\n-\tif(oserror && strcmp(path->s, \"os\") == 0) {\n-\t\tSym *s;\n-\t\ts = pkglookup(\"Error\", p);\n-\t\ts->def = typenod(errortype);\n-\t}\n-\n \treturn p;\n }\
コアとなるコードの解説
src/cmd/gc/go.h
の変更
削除された行: EXTERN int oserror;
これは、oserror
という名前の整数型変数の外部宣言です。EXTERN
キーワードは、この変数が他のファイルで定義されていることを示します。この変数は、GOEXPERIMENT=os.Error
が有効であるかどうかをコンパイラ全体で共有するためのフラグとして使用されていました。この行の削除は、oserror
フラグがもはやコンパイラにとって不要になったことを意味します。
src/cmd/gc/lex.c
の変更
削除された行: {"os.Error", &oserror},
この行は、exper
という配列の一部でした。exper
配列は、GOEXPERIMENT
環境変数で指定できる実験フラグの名前と、それに対応するコンパイラ内部のフラグ変数のアドレスをマッピングしていました。"os.Error"
という文字列がGOEXPERIMENT
の値として渡された場合、oserror
変数が設定されるように定義されていました。この行の削除により、コンパイラはGOEXPERIMENT=os.Error
という指定を認識しなくなり、関連する内部フラグも設定されなくなります。
src/cmd/gc/subr.c
の変更
削除されたブロック:
// If the compiler was built with
// GOEXPERIMENT=os.Error
// define os.Error as an alias for error.
// Terrible and won't last long, but useful for transitions.
if(oserror && strcmp(path->s, "os") == 0) {
Sym *s;
s = pkglookup("Error", p);
s->def = typenod(errortype);
}
このコードブロックは、mkpkg
関数内に存在していました。mkpkg
関数は、パッケージがコンパイラによって処理される際に呼び出される可能性があります。
if(oserror && strcmp(path->s, "os") == 0)
: この条件文は、oserror
フラグが真(つまりGOEXPERIMENT=os.Error
が有効)であり、かつ現在処理しているパッケージのパスが"os"
である場合にのみ、内部のロジックを実行するようにしていました。Sym *s; s = pkglookup("Error", p);
:os
パッケージ内でError
という名前のシンボルを検索します。s->def = typenod(errortype);
: 検索されたError
シンボルの定義を、Goの組み込みerror
型(errortype
)に設定します。これにより、コンパイラはos.Error
をerror
型として扱うようになります。
このブロック全体の削除は、os.Error
をerror
型へのエイリアスとして扱うコンパイラの振る舞いが完全に廃止されたことを意味します。これにより、Go言語のエラーハンドリングは、error
インターフェースに一本化され、os.Error
という概念はコンパイラレベルではサポートされなくなりました。
関連リンク
- 元のコミット (CL 5330066): https://golang.org/cl/5330066
- このコミット (CL 5333053): https://golang.org/cl/5333053
参考にした情報源リンク
- Go言語のエラーハンドリングに関する情報: https://go.dev/blog/error-handling-and-go
GOEXPERIMENT
に関する一般的な情報(Go言語の実験的な機能について): https://go.dev/doc/go1.25#goexperiment (Go 1.25のリリースノートですが、GOEXPERIMENT
の概念を理解するのに役立ちます)- Google Web Searchの結果:
GOEXPERIMENT os.Error golang
の検索結果 (https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFajbuiXL2qQmuPX0JRzR3FRg6_TaOeC4O4-HtbOz3Hi2CO5l_4zaw98yuRF9jsuOu6RHaI5zAd-295OdjoE1YAlLi5SZbSHSG8wEsmssiE) - Go言語の
os
パッケージに関する情報: https://pkg.go.dev/os