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

[インデックス 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 インターフェースを満たすとみなされます。これにより、開発者はカスタムエラー型を簡単に定義し、標準的な方法でエラー情報を伝達できます。

panicrecover

Go言語には、回復不可能なエラーやプログラミング上のバグを示すために panic というメカニズムも存在します。panic が発生すると、現在の関数の実行が停止し、遅延関数(defer で登録された関数)が実行され、その後呼び出しスタックを遡ってパニックが伝播します。スタックの途中で recover 関数を呼び出すことで、パニックから回復し、プログラムの実行を継続することも可能ですが、これは通常、サーバーのクラッシュを防ぐなどの限定的な状況でのみ使用されます。

runtime.Error は、ランタイムパニックによって発生するエラーを表すインターフェースであり、このコミットによって error インターフェースを満たすように変更されました。これは、パニックもまた、最終的には error インターフェースを通じて表現されるべきであるというGoの設計思想を反映しています。

技術的詳細

このコミットは、Go言語の仕様書 doc/go_spec.html に以下の重要な変更を加えています。

  1. 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
    
  2. 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 がどのように関数の戻り値として使用されるかが示されています。
  3. runtime.Errorerror インターフェースへの準拠: 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.ErrorError() メソッドを持つことが保証され、通常の error と同様に扱えるようになりました。

  4. devnullWrite メソッドの戻り値型の変更: func (devnull) Write(p []byte) (n int, _ os.Error) の戻り値型が os.Error から error に変更されました。これは、Go 1.0 リリースに向けて os.Errorerror インターフェースに統合される過程の一部であり、より汎用的な 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検索結果に基づく)