[インデックス 10176] ファイルの概要
このコミットは、Go言語の公式仕様書である doc/go_spec.html
に、error
型に関する記述を追加し、既存の型定義リストに error
を含めるように更新するものです。これにより、Go言語におけるエラーハンドリングの基本的なメカニズムである error
インターフェースが、言語仕様として明確に定義されました。
コミット
commit d9877e22fe205800029ef3d39b015b2def5a79b0
Author: Russ Cox <rsc@golang.org>
Date: Tue Nov 1 21:45:02 2011 -0400
spec: add error
R=golang-dev, dsymonds, r, r
CC=golang-dev
https://golang.org/cl/5308072
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/d9877e22fe205800029ef3d39b015b2def5a79b0
元コミット内容
このコミットの目的は、Go言語の仕様書に error
型の定義を追加することです。具体的には、doc/go_spec.html
ファイルが更新され、error
が組み込み型として明示され、そのインターフェース定義とエラーハンドリングにおける慣習的な利用方法が説明されています。
変更の背景
Go言語は、エラーハンドリングにおいて例外機構ではなく、多値戻り値と error
インターフェースを使用する独特のアプローチを採用しています。このコミットが行われた2011年11月時点では、Go言語はまだ比較的新しい言語であり、その仕様は進化の途中にありました。
この変更の背景には、Go言語におけるエラーハンドリングの慣習を公式な言語仕様として明文化し、開発者に対して error
型の重要性とその利用方法を明確に伝える必要があったと考えられます。特に、error
が単なるライブラリの型ではなく、言語自体に組み込まれた「predeclared type(事前宣言された型)」であることを強調することで、Goのエラーハンドリング哲学をより強固なものにする意図があったと推測されます。
また、runtime.Error
型が error
インターフェースを満たすように変更されたことは、ランタイムパニックもまた、error
インターフェースを通じて統一的に扱われるべきであるという設計思想を示唆しています。これにより、Goプログラムにおけるエラーとパニックの概念が、より一貫性のある形で整理されました。
前提知識の解説
Go言語におけるエラーハンドリングの哲学
Go言語は、JavaやPythonのような例外処理(try-catchメカニズム)を採用していません。代わりに、関数がエラーを返す場合は、戻り値の最後の要素として error
型の値を返すという慣習が広く用いられています。エラーがない場合は nil
を返します。このアプローチは、エラーが通常の制御フローの一部として扱われるべきであり、呼び出し元がエラーの発生を明示的にチェックし、適切に処理することを強制するという哲学に基づいています。
error
インターフェース
Go言語における error
は、以下のように定義された組み込みのインターフェースです。
type error interface {
Error() string
}
このインターフェースは、Error()
というシグネチャを持つメソッドを一つだけ持ち、これはエラーに関する文字列形式の記述を返します。任意の型がこの Error()
メソッドを実装していれば、その型は error
インターフェースを満たすとみなされます。これにより、開発者はカスタムエラー型を簡単に定義し、標準的な方法でエラー情報を伝達できます。
panic
と recover
Go言語には、回復不可能なエラーやプログラミング上のバグを示すために panic
というメカニズムも存在します。panic
が発生すると、現在の関数の実行が停止し、遅延関数(defer
で登録された関数)が実行され、その後呼び出しスタックを遡ってパニックが伝播します。スタックの途中で recover
関数を呼び出すことで、パニックから回復し、プログラムの実行を継続することも可能ですが、これは通常、サーバーのクラッシュを防ぐなどの限定的な状況でのみ使用されます。
runtime.Error
は、ランタイムパニックによって発生するエラーを表すインターフェースであり、このコミットによって error
インターフェースを満たすように変更されました。これは、パニックもまた、最終的には error
インターフェースを通じて表現されるべきであるというGoの設計思想を反映しています。
技術的詳細
このコミットは、Go言語の仕様書 doc/go_spec.html
に以下の重要な変更を加えています。
-
error
型の組み込み型としての明示: 以前の仕様では、組み込み型(Basic types)のリストにerror
は含まれていませんでした。このコミットにより、bool
,byte
,complex64
などと同じレベルでerror
が「Types」として明示的にリストアップされました。これは、error
が言語の基本的な構成要素の一つであることを強調しています。変更前:
Basic types: bool byte complex64 complex128 float32 float64 int8 int16 int32 int64 rune string uint8 uint16 uint32 uint64 Architecture-specific convenience types: int uint uintptr
変更後:
Types: bool byte complex64 complex128 error float32 float64 int int8 int16 int32 int64 rune string uint uint8 uint16 uint32 uint64 uintptr
-
Errors
セクションの追加: 新たに<h2 id="Errors">Errors</h2>
というセクションが追加され、error
インターフェースの定義と、その慣習的な利用方法が詳細に説明されています。error
インターフェースの定義 (type error interface { Error() string }
) が明記されました。nil
値がエラーがないことを表す慣習が説明されています。- ファイル読み込み関数の例 (
func Read(f *File, b []byte) (n int, err error)
) を用いて、error
がどのように関数の戻り値として使用されるかが示されています。
-
runtime.Error
のerror
インターフェースへの準拠:Run-time panics
のセクションにおいて、runtime.Error
型がerror
インターフェースを満たすように記述が変更されました。変更前:
That type defines at least the method <code>String() string</code>. The exact error values that represent distinct run-time error conditions are unspecified, at least for now.
変更後:
That type satisfies the predeclared interface type <a href="#Errors"><code>error</code></a>. The exact error values that represent distinct run-time error conditions are unspecified.
これにより、
runtime.Error
もError()
メソッドを持つことが保証され、通常のerror
と同様に扱えるようになりました。 -
devnull
のWrite
メソッドの戻り値型の変更:func (devnull) Write(p []byte) (n int, _ os.Error)
の戻り値型がos.Error
からerror
に変更されました。これは、Go 1.0 リリースに向けてos.Error
がerror
インターフェースに統合される過程の一部であり、より汎用的なerror
インターフェースを使用するよう推奨する変更です。変更前:
func (devnull) Write(p []byte) (n int, _ os.Error) {
変更後:
func (devnull) Write(p []byte) (n int, _ error) {
これらの変更は、Go言語のエラーハンドリングモデルをより明確にし、error
インターフェースが言語の根幹をなす要素であることを公式に位置づける上で非常に重要です。
コアとなるコードの変更箇所
変更は doc/go_spec.html
ファイルに対して行われています。
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1,5 +1,5 @@
<!-- title The Go Programming Language Specification -->
-<!-- subtitle Version of October 25, 2011 -->
+<!-- subtitle Version of November 1, 2011 -->
<!--
TODO
@@ -1498,12 +1498,10 @@ the body of any nested function.\n The following identifiers are implicitly declared in the universe block:\n </p>\n <pre class=\"grammar\">\n-Basic types:\n-\tbool byte complex64 complex128 float32 float64\n-\tint8 int16 int32 int64 rune string uint8 uint16 uint32 uint64\n-\n-Architecture-specific convenience types:\n-\tint uint uintptr\n+Types:\n+\tbool byte complex64 complex128 error float32 float64\n+\tint int8 int16 int32 int64 rune string\n+\tuint uint8 uint16 uint32 uint64 uintptr\n \n Constants:\n \ttrue false iota\n@@ -4323,7 +4321,7 @@ func complex_f3() (re float64, im float64) {\n \treturn\n }\n \n-func (devnull) Write(p []byte) (n int, _ os.Error) {\n+func (devnull) Write(p []byte) (n int, _ error) {\n \tn = len(p)\n \treturn\n }\n@@ -5172,6 +5170,28 @@ the <code>init</code> functions: it will not start the next\n the previous one has returned.\n </p>\n \n+<h2 id=\"Errors\">Errors</h2>\n+\n+<p>\n+The predeclared type <code>error</code> is defined as\n+</p>\n+\n+<pre>\n+type error interface {\n+\tError() string\n+}\n+</pre>\n+\n+<p>\n+It is the conventional interface for representing an error condition,\n+with the nil value representing no error.\n+For instance, a function to read data from a file might be defined:\n+</p>\n+\n+<pre>\n+func Read(f *File, b []byte) (n int, err error)\n+</pre>\n+\n <h2 id=\"Run_time_panics\">Run-time panics</h2>\n \n <p>\n@@ -5179,18 +5199,18 @@ Execution errors such as attempting to index an array out\n of bounds trigger a <i>run-time panic</i> equivalent to a call of\n the built-in function <a href=\"#Handling_panics\"><code>panic</code></a>\n with a value of the implementation-defined interface type <code>runtime.Error</code>.\n-That type defines at least the method\n-<code>String() string</code>. The exact error values that\n-represent distinct run-time error conditions are unspecified,\n-at least for now.\n+That type satisfies the predeclared interface type \n+<a href=\"#Errors\"><code>error</code></a>.\n+The exact error values that\n+represent distinct run-time error conditions are unspecified.\n </p>\n \n <pre>\n package runtime\n \n type Error interface {\n-\tString() string\n-\t// and perhaps others\n+\terror\n+\t// and perhaps other methods\n }\n </pre>\n \n```
## コアとなるコードの解説
このコミットは、Go言語の仕様書に `error` 型に関する以下の重要な変更を加えています。
1. **仕様書のバージョン日付の更新**:
`<!-- subtitle Version of October 25, 2011 -->` から `<!-- subtitle Version of November 1, 2011 -->` へと、仕様書のバージョン日付が更新されています。これは、このコミットがGo言語の仕様に正式な変更を加えるものであることを示しています。
2. **組み込み型リストへの `error` の追加**:
`Basic types` と `Architecture-specific convenience types` という分類が `Types` に統合され、その中に `error` が追加されました。これにより、`error` が `bool` や `int` などと同様に、Go言語に最初から組み込まれている基本的な型であることが明確に示されました。これは、`error` が単なるライブラリの型ではなく、言語設計の根幹をなす要素であることを強調しています。
3. **`devnull` の `Write` メソッドの戻り値型の変更**:
`func (devnull) Write(p []byte) (n int, _ os.Error)` の戻り値型が `os.Error` から `error` に変更されました。これは、Go 1.0 リリースに向けて `os.Error` が `error` インターフェースに統合される過程の一部であり、より汎用的な `error` インターフェースを使用するよう推奨する変更です。
4. **`Errors` セクションの新規追加**:
Go言語におけるエラーハンドリングの核心である `error` インターフェースについて、専用のセクションが追加されました。
- `error` インターフェースの定義 (`type error interface { Error() string }`) が明記されています。これは、`error` が `Error()` メソッドを持つ任意の型として機能することを意味します。
- `nil` 値がエラーがないことを表す慣習が説明されています。これはGoのエラーハンドリングの基本であり、エラーの有無を明示的にチェックする文化を促進します。
- `func Read(f *File, b []byte) (n int, err error)` のような関数のシグネチャ例が示され、`error` がどのように関数の戻り値として使用されるかの典型的なパターンが提示されています。
5. **`runtime.Error` の `error` インターフェースへの準拠の明記**:
`Run-time panics` のセクションにおいて、`runtime.Error` 型が `error` インターフェースを満たすように記述が変更されました。以前は `String() string` メソッドを持つとだけ書かれていましたが、この変更により `runtime.Error` も `error` インターフェースとして扱えることが明確になりました。これは、パニックによって発生するエラーも、Goのエラーハンドリングの統一的な枠組みの中に位置づけられることを示唆しています。
これらの変更は、Go言語のエラーハンドリングモデルを公式に定義し、その一貫性と重要性を開発者に伝える上で極めて重要な役割を果たしています。
## 関連リンク
* GitHubコミットページ: [https://github.com/golang/go/commit/d9877e22fe205800029ef3d39b015b2def5a79b0](https://github.com/golang/go/commit/d9877e22fe205800029ef3d39b015b2def5a79b0)
* Go CL (Change List): [https://golang.org/cl/5308072](https://golang.org/cl/5308072)
## 参考にした情報源リンク
* Go言語公式ドキュメント: [https://go.dev/doc/](https://go.dev/doc/)
* Effective Go - Error Handling: [https://go.dev/doc/effective_go#errors](https://go.dev/doc/effective_go#errors)
* Go by Example: Errors: [https://gobyexample.com/errors](https://gobyexample.com/errors)
* Go言語の `error` インターフェースに関する一般的な情報源 (Web検索結果に基づく)