[インデックス 10183] ファイルの概要
このコミットは、Go言語のランタイムパッケージにおけるエラーハンドリングのインターフェース定義を、より標準的なerror
インターフェースに準拠するように更新するものです。具体的には、エラーインターフェースのメソッド名をString()
からError()
に変更し、それに伴う関連する型のメソッド名も修正しています。
コミット
- コミットハッシュ:
c14f71c78839f51652d6420fb03b3538914ad062
- 作者: Russ Cox rsc@golang.org
- コミット日時: 2011年11月1日 火曜日 21:48:27 -0400
- コミットメッセージ:
runtime: update for error R=golang-dev, iant, r CC=golang-dev https://golang.org/cl/5306075
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/c14f71c78839f51652d6420fb03b3538914ad062
元コミット内容
Goランタイムのエラー処理を更新し、標準のerror
インターフェースに合わせる変更。
変更の背景
Go言語では、エラーハンドリングは非常に重要な要素であり、標準ライブラリ全体でerror
インターフェースが広く利用されています。このインターフェースは、Error() string
というシグネチャを持つ単一のメソッドを定義しており、エラーの詳細を文字列として返すことを期待します。
このコミットが行われた2011年11月時点では、Go言語はまだ発展途上にあり、APIやインターフェースの設計が固まりつつある時期でした。このコミット以前のruntime
パッケージ内のエラー関連の型は、エラーメッセージを返すためにString() string
というメソッド名を使用していた可能性があります。しかし、Goの標準的なエラーハンドリングの慣習が確立されるにつれて、エラーを表す型はerror
インターフェースを実装すべきであるという方向性が明確になりました。
この変更の背景には、Go言語全体のエラーハンドリングの一貫性を保ち、開発者がエラーを扱う際に統一された方法を提供しようとする意図があります。String()
メソッドは一般的に型の文字列表現を返すために使われますが、エラーメッセージの取得にはError()
メソッドがより適切であり、Goの慣習に合致します。これにより、runtime
パッケージが生成するエラーも、他のGoコードで生成されるエラーと同様に、標準的なerror
インターフェースとして扱えるようになります。
前提知識の解説
Go言語のerror
インターフェース
Go言語におけるエラーハンドリングの基本は、組み込みのerror
インターフェースです。このインターフェースは以下のように定義されています。
type error interface {
Error() string
}
このインターフェースを実装する型は、Error() string
というメソッドを持つ必要があります。このメソッドは、エラーに関する詳細な情報を含む文字列を返します。Goの関数は、エラーが発生した場合に、通常、戻り値の最後の引数としてerror
型の値を返します。エラーがない場合はnil
を返します。
String()
メソッドとError()
メソッドの違い
-
String() string
メソッド: Go言語では、fmt
パッケージのStringer
インターフェースを実装するためにString() string
メソッドがよく使われます。Stringer
インターフェースは、任意の型の値を人間が読める形式の文字列に変換するために使用されます。例えば、構造体の内容をデバッグ目的で表示する場合などに利用されます。 -
Error() string
メソッド: これはerror
インターフェースの一部であり、エラーメッセージを返すために特別に設計されています。Goの慣習として、エラーが発生したことを示すためにこのメソッドが使用されます。
このコミットの変更は、runtime
パッケージ内のエラー関連の型が、単なる文字列表現を提供するStringer
ではなく、Goの標準的なエラーとして振る舞うべきであるという設計思想の転換を示しています。
技術的詳細
このコミットの技術的な核心は、runtime
パッケージ内で定義されているエラー関連の型が、Goの組み込みerror
インターフェースに準拠するように修正された点です。
-
runtime.Error
インターフェースの変更: コミット前のruntime.Error
インターフェースは、おそらくString() string
メソッドを要求していました。このコミットにより、runtime.Error
インターフェース自体が、Goの組み込みerror
インターフェースを埋め込む形に変更されました。- type Error interface { - String() string + type Error interface { + error
これは、
runtime.Error
を実装する型が、自動的にerror
インターフェースのError() string
メソッドを持つことを意味します。これにより、runtime.Error
型の値は、どこでもerror
型の値として扱えるようになり、Goのエラーハンドリングの統一性が向上します。 -
具体的なエラー型のメソッド名変更:
runtime
パッケージ内で定義されている具体的なエラー型(例:TypeAssertionError
、errorString
)が、String() string
メソッドをError() string
メソッドにリネームしました。- func (e *TypeAssertionError) String() string { + func (e *TypeAssertionError) Error() string {
- func (e errorString) String() string { + func (e errorString) Error() string {
これにより、これらの型が
runtime.Error
インターフェース(そして間接的にerror
インターフェース)の要件を満たすようになります。 -
printany
関数の更新:printany
関数は、様々な型の値を表示するための内部的なヘルパー関数です。この関数に、error
型の値を特別に処理するcase
が追加されました。+ case error: + print(v.Error())
これは、
printany
がerror
型の値を受け取った際に、そのError()
メソッドを呼び出してエラーメッセージを表示するように変更されたことを意味します。これにより、ランタイム内部でのエラーの表示方法も、標準的なerror
インターフェースの慣習に沿うようになりました。
これらの変更は、Go言語のランタイムが生成するエラーが、言語全体で期待されるエラーハンドリングのパターンに完全に統合されることを保証します。
コアとなるコードの変更箇所
src/pkg/runtime/error.go
ファイルにおける変更点です。
--- a/src/pkg/runtime/error.go
+++ b/src/pkg/runtime/error.go
@@ -6,7 +6,7 @@ package runtime
// The Error interface identifies a run time error.
type Error interface {
- String() string
+ error
// RuntimeError is a no-op function but
// serves to distinguish types that are runtime
@@ -28,7 +28,7 @@ type TypeAssertionError struct {
func (*TypeAssertionError) RuntimeError() {}
-func (e *TypeAssertionError) String() string {
+func (e *TypeAssertionError) Error() string {
inter := e.interfaceString
if inter == "" {
inter = "interface"
@@ -98,7 +98,7 @@ type errorString string
func (e errorString) RuntimeError() {}
-func (e errorString) String() string {
+func (e errorString) Error() string {
return "runtime error: " + string(e)
}
@@ -123,6 +123,8 @@ func printany(i interface{}) {
\t\tprint(\"nil\")
\tcase stringer:
\t\tprint(v.String())
+\tcase error:
+\t\tprint(v.Error())
\tcase int:
\t\tprint(v)
\tcase string:
コアとなるコードの解説
-
type Error interface { error }
: これは、runtime
パッケージが定義するError
インターフェースが、Goの組み込みerror
インターフェースを埋め込むように変更されたことを示しています。これにより、runtime.Error
を実装する型は、自動的にError() string
メソッドを持つことが保証されます。これは、Goのエラーハンドリングの標準的な慣習に準拠するための重要な変更です。 -
func (e *TypeAssertionError) Error() string { ... }
:TypeAssertionError
型は、型アサーションが失敗した際に発生するランタイムエラーを表します。この変更により、エラーメッセージを返すメソッドの名前がString()
からError()
に変更されました。これにより、このエラー型が標準のerror
インターフェースの要件を満たし、他のGoコードで一般的なエラーとして扱えるようになります。 -
func (e errorString) Error() string { ... }
:errorString
型は、単純な文字列ベースのランタイムエラーを表すために使用されます。同様に、この型のエラーメッセージを返すメソッドの名前もString()
からError()
に変更されました。これにより、errorString
も標準のerror
インターフェースに準拠します。 -
case error: print(v.Error())
:printany
関数は、ランタイム内部で様々な型の値をデバッグ目的などで表示するために使用される可能性があります。この変更は、printany
がerror
型の値を受け取った場合に、そのError()
メソッドを呼び出してエラーメッセージを表示するように指示しています。これは、ランタイム内部でのエラーの取り扱いも、標準的なerror
インターフェースの慣習に沿うように調整されたことを意味します。
これらの変更は、Go言語のエラーハンドリングの設計原則に沿って、ランタイムが生成するエラーがより一貫性のある方法で扱われるようにするためのものです。
関連リンク
- Go CL (Code Review) リンク: https://golang.org/cl/5306075
参考にした情報源リンク
- Go言語の
error
インターフェースに関する公式ドキュメントやチュートリアル(一般的なGoのエラーハンドリングの知識に基づくため、特定のURLは記載しませんが、Goの公式ドキュメントやEffective Goなどが参考になります)。