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

[インデックス 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インターフェースに準拠するように修正された点です。

  1. 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のエラーハンドリングの統一性が向上します。

  2. 具体的なエラー型のメソッド名変更: runtimeパッケージ内で定義されている具体的なエラー型(例: TypeAssertionErrorerrorString)が、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インターフェース)の要件を満たすようになります。

  3. printany関数の更新: printany関数は、様々な型の値を表示するための内部的なヘルパー関数です。この関数に、error型の値を特別に処理するcaseが追加されました。

    + 	case error:
    + 		print(v.Error())
    

    これは、printanyerror型の値を受け取った際に、その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:

コアとなるコードの解説

  1. type Error interface { error }: これは、runtimeパッケージが定義するErrorインターフェースが、Goの組み込みerrorインターフェースを埋め込むように変更されたことを示しています。これにより、runtime.Errorを実装する型は、自動的にError() stringメソッドを持つことが保証されます。これは、Goのエラーハンドリングの標準的な慣習に準拠するための重要な変更です。

  2. func (e *TypeAssertionError) Error() string { ... }: TypeAssertionError型は、型アサーションが失敗した際に発生するランタイムエラーを表します。この変更により、エラーメッセージを返すメソッドの名前がString()からError()に変更されました。これにより、このエラー型が標準のerrorインターフェースの要件を満たし、他のGoコードで一般的なエラーとして扱えるようになります。

  3. func (e errorString) Error() string { ... }: errorString型は、単純な文字列ベースのランタイムエラーを表すために使用されます。同様に、この型のエラーメッセージを返すメソッドの名前もString()からError()に変更されました。これにより、errorStringも標準のerrorインターフェースに準拠します。

  4. case error: print(v.Error()): printany関数は、ランタイム内部で様々な型の値をデバッグ目的などで表示するために使用される可能性があります。この変更は、printanyerror型の値を受け取った場合に、そのError()メソッドを呼び出してエラーメッセージを表示するように指示しています。これは、ランタイム内部でのエラーの取り扱いも、標準的なerrorインターフェースの慣習に沿うように調整されたことを意味します。

これらの変更は、Go言語のエラーハンドリングの設計原則に沿って、ランタイムが生成するエラーがより一貫性のある方法で扱われるようにするためのものです。

関連リンク

参考にした情報源リンク

  • Go言語のerrorインターフェースに関する公式ドキュメントやチュートリアル(一般的なGoのエラーハンドリングの知識に基づくため、特定のURLは記載しませんが、Goの公式ドキュメントやEffective Goなどが参考になります)。