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

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

このコミットは、Go言語の標準ライブラリ内の複数のパッケージにおいて、エラー変数の命名規則を FooError から ErrFoo へと変更するものです。これは、Go言語におけるエラー命名の慣習に沿ったものであり、コードの一貫性と可読性を向上させることを目的としています。具体的には、archive/tararchive/zipcompress/gzipcompress/zlibcrypto/bcrypt といったパッケージ内のエラー変数が影響を受けています。

コミット

commit 37d2f8190d5477c306675ec17cfc05499630fe63
Author: Brad Fitzpatrick <bradfitz@golang.org>
Date:   Tue Jan 24 11:48:48 2012 -0800

    rename FooError vars to ErrFoo
    
    R=golang-dev, rsc
    CC=golang-dev
    https://golang.org/cl/5574056

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/37d2f8190d5477c306675ec17cfc05499630fe63

元コミット内容

このコミットの目的は、「FooError」という命名パターンを持つエラー変数を「ErrFoo」という命名パターンに変更することです。これは、Go言語の標準ライブラリ全体でエラー変数の命名規則を統一し、より慣用的なスタイルに合わせるためのリファクタリング作業の一環です。

変更の背景

Go言語では、コードの可読性と一貫性を非常に重視しています。特に、エラーハンドリングはGo言語の設計思想の中心的な部分であり、エラーの命名規則もその一部です。初期のGo言語のコードベースでは、エラー変数の命名に様々なパターンが存在していました。しかし、Goコミュニティと開発チームの間で、エラー変数は Err プレフィックスを付けて、その後にエラーの種類を示すキャメルケースの名前を続けるという慣習が確立されていきました。

このコミットが行われた2012年頃は、Go言語がまだ比較的新しく、標準ライブラリのAPIや慣習が成熟していく過程にありました。このようなリファクタリングは、言語の進化とともにベストプラクティスが確立され、それらを既存のコードベースに適用していく典型的な例です。FooError から ErrFoo への変更は、エラー変数が error インターフェースを実装する値であることを明確にし、他の変数名との混同を避けるためのものです。これにより、開発者がコードを読んだ際に、その変数がエラー値であることを直感的に理解できるようになります。

前提知識の解説

Go言語におけるエラーハンドリング

Go言語には例外処理の仕組み(try-catchなど)は存在せず、エラーは関数の戻り値として明示的に扱われます。慣習として、エラーを返す関数は最後の戻り値として error 型を返します。error は組み込みのインターフェースであり、Error() string メソッドを持ちます。

type error interface {
    Error() string
}

errors.New 関数

Go言語の標準ライブラリには errors パッケージが含まれており、その中の errors.New 関数は、シンプルなエラー値を生成するために使用されます。

func New(text string) error

この関数は、指定された文字列をエラーメッセージとして持つ新しい error 型の値を返します。このコミットで変更されている var 宣言されたエラー変数は、通常、この errors.New を使って初期化されています。

Go言語の命名規則

Go言語には、変数、関数、型などの命名に関する明確な慣習があります。

  • エクスポートされる識別子: パッケージ外からアクセス可能な識別子(関数、変数、型など)は、大文字で始まります。
  • エクスポートされない識別子: パッケージ内でのみ使用される識別子は、小文字で始まります。
  • エラー変数: 慣習として、エクスポートされるエラー変数は Err プレフィックスを付けて、その後にエラーの種類を示すキャメルケースの名前を続けます(例: ErrNotFound, ErrInvalidParameter)。これは、その変数が error 型のインスタンスであることを明確に示し、他の種類の変数と区別しやすくするためです。

このコミットは、まさにこの「エラー変数」の命名慣習に沿った変更を行っています。

技術的詳細

このコミットの技術的な変更は非常にシンプルですが、Go言語の設計思想と慣習を反映しています。

  1. 命名規則の統一: 既存の FooError という形式で宣言されていたエラー変数を、ErrFoo という形式に一括してリネームしています。例えば、HeaderErrorErrHeader に、FormatErrorErrFormat に変更されています。
  2. 影響範囲: この変更は、src/pkg/archive/tarsrc/pkg/archive/zipsrc/pkg/compress/gzipsrc/pkg/compress/zlibsrc/pkg/crypto/bcrypt といった複数の標準ライブラリパッケージにわたっています。これは、Go言語の標準ライブラリ全体で一貫したエラー命名規則を適用しようとする意図を示しています。
  3. 参照箇所の更新: 変数名が変更されたため、その変数を参照しているすべての箇所(例えば、if err == HeaderError のような比較)も新しい変数名 (if err == ErrHeader) に更新されています。これにより、コンパイルエラーを防ぎ、コードの整合性を保っています。
  4. テストコードの更新: 関連するテストファイル (_test.go ファイル) も、変更されたエラー変数名に合わせて更新されています。これにより、テストが引き続き正しく機能し、リファクタリングによって既存の動作が損なわれていないことを保証しています。

この変更は、機能的な変更を一切伴いません。純粋にコードのスタイルと一貫性を向上させるためのリファクタリングです。しかし、このような一貫性は、大規模なコードベースにおいて開発者がコードを理解し、保守する上で非常に重要となります。

コアとなるコードの変更箇所

src/pkg/archive/tar/reader.go における変更を例として示します。

--- a/src/pkg/archive/tar/reader.go
+++ b/src/pkg/archive/tar/reader.go
@@ -18,7 +18,7 @@ import (
 )
 
 var (
-	HeaderError = errors.New("invalid tar header")
+	ErrHeader = errors.New("invalid tar header")
 )
 
 // A Reader provides sequential access to the contents of a tar archive.
@@ -123,13 +123,13 @@ func (tr *Reader) readHeader() *Header {
 		if bytes.Equal(header, zeroBlock[0:blockSize]) {
 			tr.err = io.EOF
 		} else {
-			tr.err = HeaderError // zero block and then non-zero block
+			tr.err = ErrHeader // zero block and then non-zero block
 		}
 		return nil
 	}
 
 	if !tr.verifyChecksum(header) {
-		tr.err = HeaderError
+		tr.err = ErrHeader
 		return nil
 	}
 
@@ -188,7 +188,7 @@ func (tr *Reader) readHeader() *Header {
 	}
 
 	if tr.err != nil {
-		tr.err = HeaderError
+		tr.err = ErrHeader
 		return nil
 	}

コアとなるコードの解説

上記の差分は、archive/tar パッケージ内の reader.go ファイルにおける変更を示しています。

  1. エラー変数の宣言:

    -	HeaderError = errors.New("invalid tar header")
    +	ErrHeader = errors.New("invalid tar header")
    

    ここで、HeaderError という名前で宣言されていた error 型の変数が ErrHeader に変更されています。errors.New 関数を使って「invalid tar header」というメッセージを持つ新しいエラー値が作成され、この変数に割り当てられています。この変更は、Go言語のエラー命名慣習 (Err プレフィックス) に従うものです。

  2. エラー変数の参照箇所の更新:

    -			tr.err = HeaderError // zero block and then non-zero block
    +			tr.err = ErrHeader // zero block and then non-zero block
    
    -		tr.err = HeaderError
    +		tr.err = ErrHeader
    
    -		tr.err = HeaderError
    +		tr.err = ErrHeader
    

    Reader 型のメソッド内で、以前 HeaderError を使用してエラーを割り当てていたすべての箇所が、新しい変数名 ErrHeader に更新されています。これは、変数名のリネームに伴う必須の変更であり、コードの機能には影響を与えません。

同様の変更が、archive/zipcompress/gzipcompress/zlibcrypto/bcrypt の各パッケージ内の関連ファイルでも行われています。例えば、zip パッケージでは FormatErrorErrFormat に、UnsupportedMethodErrAlgorithm に、ChecksumErrorErrChecksum に変更されています。bcrypt パッケージでは MismatchedHashAndPasswordErrorErrMismatchedHashAndPassword に、HashTooShortErrorErrHashTooShort に変更されています。

これらの変更は、Go言語の標準ライブラリ全体でエラー変数の命名規則を統一し、コードベースの一貫性と可読性を高めるための重要なステップでした。

関連リンク

参考にした情報源リンク