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

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

このコミットは、Go言語のコンパイラ(gc)において、以前追加された実験的な機能であるGOEXPERIMENT=os.Errorを元に戻すものです。この機能は、os.Errorerror型へのエイリアスとして定義するものでしたが、コミットメッセージにある通り、短期間で削除されることが約束されていました。

コミット

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.Errorerror

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つのファイルに分散していました。

  1. src/cmd/gc/go.h: コンパイラのグローバルなヘッダーファイルで、oserrorという変数が宣言されていました。この変数は、GOEXPERIMENT=os.Errorが有効かどうかを示すフラグとして機能していました。
  2. src/cmd/gc/lex.c: 字句解析器に関連するファイルで、GOEXPERIMENT環境変数を解析し、対応する内部フラグ(oserrorなど)を設定するロジックが含まれていました。"os.Error"という文字列と&oserrorのペアが、実験フラグのリストから削除されています。
  3. src/cmd/gc/subr.c: コンパイラのサブルーチンが含まれるファイルで、mkpkg関数内にos.Errorerror型へのエイリアスとして定義する具体的なロジックが含まれていました。このロジックは、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.Errorerror型として扱うようになります。

このブロック全体の削除は、os.Errorerror型へのエイリアスとして扱うコンパイラの振る舞いが完全に廃止されたことを意味します。これにより、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