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

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

このコミットは、Go言語の標準ライブラリであるfmtパッケージ内のスキャン関連のエラーメッセージから、冗長な「Scan:」プレフィックスを削除する変更です。この変更により、エラーメッセージが一貫性を持ち、より簡潔になります。

コミット

  • コミットハッシュ: 609d742e791eebceddaeae419b3b909594f4e404
  • Author: Rob Pike r@golang.org
  • Date: Wed Jul 31 14:09:19 2013 +1000

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

https://github.com/golang/go/commit/609d742e791eebceddaeae419b3b909594f4e404

元コミット内容

fmt: remove "Scan:" prefix from error messages
The prefix was not uniformly applied and is probably better left off anyway.

Fixes #4944.

R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/12140043

変更の背景

このコミットの主な背景は、fmtパッケージのスキャン関数が生成するエラーメッセージに一貫性がなかったことです。一部のエラーメッセージには「Scan:」というプレフィックスが付与されていましたが、他のエラーメッセージには付与されていませんでした。この不均一な適用は、ユーザーがエラーメッセージを解析したり、プログラムでエラーを処理したりする際に混乱を招く可能性がありました。

コミットメッセージにある「The prefix was not uniformly applied and is probably better left off anyway.」という記述は、この不均一性を解消し、かつプレフィックス自体が冗長であるという判断を示しています。エラーメッセージは、その内容だけで十分な情報を提供できるべきであり、どの関数から発生したかを示すプレフィックスは必ずしも必要ではないという設計思想が背景にあると考えられます。

また、Fixes #4944という記述がありますが、Goの公式GitHubリポジトリではこの番号のIssueは見つかりませんでした。これは、Issueが非公開であったり、番号が変更されたり、あるいは内部的なトラッカーの番号である可能性が考えられます。しかし、この記述から、この変更が特定の問題を解決するために行われたことが示唆されます。

前提知識の解説

Go言語のfmtパッケージ

fmtパッケージは、Go言語におけるフォーマットI/Oを実装するためのパッケージです。C言語のprintfscanfに似た機能を提供し、文字列のフォーマット、標準出力への出力、文字列からの値の読み取り(スキャン)などを行います。

  • 出力関数: Printf, Sprintf, Fprintなどがあり、指定されたフォーマットに従って値を出力します。
  • 入力(スキャン)関数: Scan, Scanf, Sscan, Fscanなどがあり、入力ソース(標準入力、文字列、io.Readerなど)から値を読み取ります。これらの関数は、入力された文字列をGoのデータ型に変換する際に、型変換エラーやフォーマット不一致などの問題が発生する可能性があります。

Go言語のエラーハンドリング

Go言語では、エラーは戻り値として明示的に扱われます。関数がエラーを返す可能性がある場合、その関数の最後の戻り値は慣習的にerror型になります。errorはインターフェースであり、Error() stringメソッドを持ちます。このメソッドは、エラーに関する説明文字列を返します。

fmtパッケージのスキャン関数も、入力の解析に失敗した場合にerror型の値を返します。このコミットは、そのerrorインターフェースのError()メソッドが返す文字列の内容を変更するものです。

scan.goファイル

src/pkg/fmt/scan.goは、fmtパッケージ内でスキャン関連のロジックを実装しているファイルです。このファイルには、数値や文字列の解析、型変換、エラー報告などの内部関数が含まれています。

技術的詳細

このコミットは、fmtパッケージの内部構造体であるss(おそらく"scan state"の略)のerrorStringメソッドの呼び出し箇所を変更しています。errorStringメソッドは、スキャン処理中に発生したエラーを報告するために使用される内部ヘルパー関数です。

変更前は、errorStringメソッドに渡される文字列リテラルが「Scan: 」というプレフィックスを含んでいました。例えば、s.errorString("Scan: illegal hex digit")のように呼び出されていました。このコミットでは、このプレフィックスを削除し、s.errorString("illegal hex digit")のように、エラーメッセージの本体のみを渡すように変更しています。

これにより、errorStringメソッドが最終的に生成するエラー文字列から「Scan: 」というプレフィックスが取り除かれます。この変更は、fmtパッケージの外部API(例えばfmt.Scanfが返すエラー)に影響を与え、より簡潔なエラーメッセージがユーザーに提示されるようになります。

具体的には、以下の5つのエラーメッセージから「Scan: 」プレフィックスが削除されています。

  1. illegal hex digit (不正な16進数)
  2. no hex data for %x string (16進数文字列のデータがない)
  3. type not a pointer: (型がポインタではない)
  4. can't scan type: (型をスキャンできない) - 元はcan't handle type:
  5. expected newline (改行が期待される)

特に4番目のエラーメッセージは、プレフィックスの削除だけでなく、「can't handle type:」から「can't scan type:」へとメッセージ自体も変更されています。これは、より具体的なエラー内容を反映させるための改善と考えられます。

この変更は、エラーメッセージの生成ロジック自体を変更するものではなく、単にerrorStringに渡される文字列リテラルを変更することで、最終的なエラーメッセージの見た目を改善しています。これは、Go言語のエラーメッセージが、ユーザーにとって分かりやすく、かつプログラムで扱いやすいものであるべきという原則に基づいています。

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

diff --git a/src/pkg/fmt/scan.go b/src/pkg/fmt/scan.go
index c7e648579a..f223897a91 100644
--- a/src/pkg/fmt/scan.go
+++ b/src/pkg/fmt/scan.go
@@ -885,7 +885,7 @@ func (s *ss) hexDigit(d rune) int {
 	case 'A', 'B', 'C', 'D', 'E', 'F':
 		return 10 + digit - 'A'
 	}
-	s.errorString("Scan: illegal hex digit")
+	s.errorString("illegal hex digit")
 	return 0
 }
 
@@ -915,7 +915,7 @@ func (s *ss) hexString() string {
 		s.buf.WriteByte(b)
 	}
 	if len(s.buf) == 0 {
-		s.errorString("Scan: no hex data for %x string")
+		s.errorString("no hex data for %x string")
 		return ""
 	}
 	return string(s.buf)
@@ -994,7 +994,7 @@ func (s *ss) scanOne(verb rune, arg interface{}) {
 		val := reflect.ValueOf(v)
 		ptr := val
 		if ptr.Kind() != reflect.Ptr {
-			s.errorString("Scan: type not a pointer: " + val.Type().String())
+			s.errorString("type not a pointer: " + val.Type().String())
 			return
 		}
 		switch v := ptr.Elem(); v.Kind() {
@@ -1010,7 +1010,7 @@ func (s *ss) scanOne(verb rune, arg interface{}) {
 			// For now, can only handle (renamed) []byte.
 			typ := v.Type()
 			if typ.Elem().Kind() != reflect.Uint8 {
-				s.errorString("Scan: can't handle type: " + val.Type().String())
+				s.errorString("can't scan type: " + val.Type().String())
 			}
 			str := s.convertString(verb)
 			v.Set(reflect.MakeSlice(typ, len(str), len(str)))
@@ -1024,7 +1024,7 @@ func (s *ss) scanOne(verb rune, arg interface{}) {
 		case reflect.Complex64, reflect.Complex128:
 			v.SetComplex(s.scanComplex(verb, v.Type().Bits()))
 		default:
-			s.errorString("Scan: can't handle type: " + val.Type().String())
+			s.errorString("can't scan type: " + val.Type().String())
 		}
 	}
 }
@@ -1057,7 +1057,7 @@ func (s *ss) doScan(a []interface{}) (numProcessed int, err error) {
 				break
 			}
 			if !isSpace(r) {
-				s.errorString("Scan: expected newline")
+				s.errorString("expected newline")
 				break
 			}
 		}

コアとなるコードの解説

上記のdiffは、src/pkg/fmt/scan.goファイル内のs.errorString()関数の呼び出し箇所における文字列リテラルの変更を示しています。

  1. hexDigit関数内:

    • s.errorString("Scan: illegal hex digit")s.errorString("illegal hex digit") に変更されました。
    • この関数は16進数の桁を解析する際に呼び出され、不正な文字が検出された場合にエラーを報告します。
  2. hexString関数内:

    • s.errorString("Scan: no hex data for %x string")s.errorString("no hex data for %x string") に変更されました。
    • この関数は16進数文字列を解析する際に呼び出され、有効な16進数データが見つからなかった場合にエラーを報告します。
  3. scanOne関数内(ポインタチェック):

    • s.errorString("Scan: type not a pointer: " + val.Type().String())s.errorString("type not a pointer: " + val.Type().String()) に変更されました。
    • fmt.Scan系の関数は、通常、値を読み取るためにポインタを引数として受け取ります。ポインタでない型が渡された場合にこのエラーが発生します。
  4. scanOne関数内(型ハンドリング):

    • s.errorString("Scan: can't handle type: " + val.Type().String())s.errorString("can't scan type: " + val.Type().String()) に変更されました。
    • これは、fmtパッケージのスキャン機能が処理できない型が渡された場合に発生するエラーです。メッセージ自体も「handle」から「scan」に変更され、よりスキャン操作に特化した表現になっています。
  5. doScan関数内(改行期待):

    • s.errorString("Scan: expected newline")s.errorString("expected newline") に変更されました。
    • これは、スキャン処理中に改行が期待される場所で別の文字が検出された場合に発生するエラーです。

これらの変更はすべて、s.errorString()に渡される文字列から「Scan: 」という固定プレフィックスを削除するものです。これにより、fmtパッケージのスキャン関数が返すエラーメッセージは、より簡潔で直接的なものになります。

関連リンク

参考にした情報源リンク

  • Go言語公式ドキュメント fmtパッケージ: https://pkg.go.dev/fmt
  • Go言語公式ドキュメント errorインターフェース: https://pkg.go.dev/builtin#error
  • Go言語におけるエラーハンドリングの基本概念
  • Go言語のreflectパッケージ(reflect.ValueOf, reflect.Type, reflect.Kindなど、型情報を扱うために使用される)

(注: Fixes #4944と記載されていますが、Goの公式GitHubリポジトリではこの番号のIssueは見つかりませんでした。)