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

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

このコミットは、Go言語の標準ライブラリである strconv パッケージ内の atoi.go ファイルに対する変更です。atoi.go は、文字列と数値の相互変換、特にASCII文字列から整数への変換("ASCII to Integer")に関連する機能を提供します。具体的には、ParseIntParseUint といった、文字列を様々な基数(進数)の整数として解析する関数が含まれています。

コミット

strconv: consistent parameter names for ParseUint

If ParseUint is like ParseInt it should have the same parameter
names, thus rename b to to base as in ParseInt's documentation.

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/6453152

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

https://github.com/golang/go/commit/db645a024d5b152ffa219ef51de0be0e8240af99

元コミット内容

ParseUint 関数のパラメータ名を b から base へと変更し、ParseInt 関数との一貫性を持たせる。

変更の背景

Go言語の標準ライブラリでは、関数のパラメータ名や振る舞いにおいて一貫性を保つことが重要視されます。このコミットの背景には、strconv パッケージ内の ParseInt 関数と ParseUint 関数の間で、基数(数値の進数)を指定するパラメータの命名に不一致があったという問題がありました。

  • ParseInt 関数は、基数を指定するパラメータに base という名前を使用していました。
  • 一方、ParseUint 関数は、同じ目的のパラメータに b という名前を使用していました。

この不一致は、開発者が両方の関数を使用する際に混乱を招く可能性があり、コードの可読性や保守性を低下させる要因となり得ました。このコミットは、このような小さな不一致を解消し、ライブラリ全体の設計原則である「一貫性」を強化することを目的としています。特に、ParseUintParseInt と同様の機能(符号なし整数版)であるならば、そのインターフェースも同様であるべきだという考えに基づいています。

前提知識の解説

strconv パッケージ

strconv パッケージは、Go言語の標準ライブラリの一部であり、基本的なデータ型(整数、浮動小数点数、真偽値など)と文字列との間の変換機能を提供します。例えば、文字列 "123" を整数 123 に変換したり、その逆を行ったりする際に使用されます。

ParseInt 関数と ParseUint 関数

これらの関数は、strconv パッケージの主要な機能の一つです。

  • ParseInt(s string, base int, bitSize int) (i int64, err error):

    • 文字列 s を、指定された base(基数、例: 2進数、10進数、16進数)で符号付き整数として解析します。
    • bitSize は、結果の整数が占めるビット数を指定します(例: 0, 8, 16, 32, 64)。0の場合、int 型のデフォルトのビットサイズが使用されます。
    • 成功した場合は int64 型の整数と nil エラーを返します。解析に失敗した場合はエラーを返します。
  • ParseUint(s string, base int, bitSize int) (n uint64, err error):

    • 文字列 s を、指定された base(基数)で符号なし整数として解析します。
    • bitSizeParseInt と同様です。
    • 成功した場合は uint64 型の符号なし整数と nil エラーを返します。解析に失敗した場合はエラーを返します。

基数(Base)

数値の基数とは、その数値を表現するために使用される異なる桁の数です。

  • 10進数(Decimal): 基数10。0から9までの10個の数字を使用します。私たちが日常的に使用する表記法です。
  • 2進数(Binary): 基数2。0と1の2個の数字を使用します。コンピュータの内部表現で使われます。
  • 8進数(Octal): 基数8。0から7までの8個の数字を使用します。
  • 16進数(Hexadecimal): 基数16。0から9までの数字と、AからFまでのアルファベット(10から15を表す)の16個の記号を使用します。

ParseIntParseUint 関数では、この base パラメータに2から36までの整数を指定できます。0を指定した場合は、文字列のプレフィックス("0x" なら16進数、"0" なら8進数、それ以外は10進数)に基づいて自動的に基数を推測します。

Go言語におけるパラメータ命名の一貫性

Go言語の設計思想では、APIのシンプルさと一貫性が非常に重視されます。これは、開発者がコードを読み書きする際の認知負荷を減らし、エラーを減らすためです。特に、類似の機能を持つ関数やメソッドでは、同じ意味を持つパラメータには同じ名前を付けることが推奨されます。今回のコミットは、このGo言語の設計原則に則った改善と言えます。

技術的詳細

このコミットの技術的な変更は非常にシンプルですが、その影響はGo言語のAPI設計における一貫性の重要性を示しています。具体的には、src/pkg/strconv/atoi.go ファイル内の ParseUint 関数のシグネチャと、その関数内部での b パラメータのすべての参照が base に変更されました。

変更前:

func ParseUint(s string, b int, bitSize int) (n uint64, err error) {
    // ... b を使用したロジック ...
}

変更後:

func ParseUint(s string, base int, bitSize int) (n uint64, err error) {
    // ... base を使用したロジック ...
}

この変更は、関数の外部インターフェース(呼び出し側から見える部分)と内部実装の両方で、パラメータ名が統一されることを意味します。コンパイラにとっては単なる変数名の変更であり、機能的な振る舞いに影響はありません。しかし、開発者にとっては、ParseIntParseUint の両方で基数を指定するパラメータが base であることが明確になり、APIの学習コストが低減されます。

また、この変更は、ParseUint 関数内の基数に関連するすべてのロジック(例えば、基数の検証、自動推測、数値変換の計算など)が、新しいパラメータ名 base を参照するように更新されたことを意味します。これにより、コードの内部的な整合性も保たれています。

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

diff --git a/src/pkg/strconv/atoi.go b/src/pkg/strconv/atoi.go
index 59ef264d17..bdd5d71f87 100644
--- a/src/pkg/strconv/atoi.go
+++ b/src/pkg/strconv/atoi.go
@@ -44,7 +44,7 @@ func cutoff64(base int) uint64 {
 }
 
 // ParseUint is like ParseInt but for unsigned numbers.
-func ParseUint(s string, b int, bitSize int) (n uint64, err error) {
+func ParseUint(s string, base int, bitSize int) (n uint64, err error) {
 	var cutoff, maxVal uint64
 
 	if bitSize == 0 {
@@ -57,32 +57,32 @@ func ParseUint(s string, b int, bitSize int) (n uint64, err error) {
 		err = ErrSyntax
 		goto Error
 
-	case 2 <= b && b <= 36:
+	case 2 <= base && base <= 36:
 		// valid base; nothing to do
 
-	case b == 0:
+	case base == 0:
 		// Look for octal, hex prefix.
 		switch {
 		case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'):
-			b = 16
+			base = 16
 			s = s[2:]
 			if len(s) < 1 {
 				err = ErrSyntax
 				goto Error
 			}
 		case s[0] == '0':
-			b = 8
+			base = 8
 		default:
-			b = 10
+			base = 10
 		}
 
 	default:
-		err = errors.New("invalid base " + Itoa(b))
+		err = errors.New("invalid base " + Itoa(base))
 		goto Error
 	}
 
 	n = 0
-	cutoff = cutoff64(b)
+	cutoff = cutoff64(base)
 	maxVal = 1<<uint(bitSize) - 1
 
 	for i := 0; i < len(s); i++ {
@@ -100,19 +100,19 @@ func ParseUint(s string, b int, bitSize int) (n uint64, err error) {
 		err = ErrSyntax
 		goto Error
 		}
-	if int(v) >= b {
+	if int(v) >= base {
 		n = 0
 		err = ErrSyntax
 		goto Error
 		}
 
 	if n >= cutoff {
-		// n*b overflows
+		// n*base overflows
 		n = 1<<64 - 1
 		err = ErrRange
 		goto Error
 		}
-	n *= uint64(b)
+	n *= uint64(base)
 
 	n1 := n + uint64(v)
 	if n1 < n || n1 > maxVal {

コアとなるコードの解説

上記のdiffは、src/pkg/strconv/atoi.go ファイルにおける ParseUint 関数の変更を示しています。

  1. 関数シグネチャの変更:

    -func ParseUint(s string, b int, bitSize int) (n uint64, err error) {
    +func ParseUint(s string, base int, bitSize int) (n uint64, err error) {
    

    ParseUint 関数の2番目のパラメータ名が b から base に変更されました。これは、このパラメータが数値の基数(進数)を表すことをより明確にし、ParseInt 関数との命名規則の一貫性を保つための変更です。

  2. 基数検証ロジックの変更:

    -	case 2 <= b && b <= 36:
    +	case 2 <= base && base <= 36:
    

    基数が有効な範囲(2から36)にあるかをチェックする条件式で、bbase に変更されています。

  3. 基数自動推測ロジックの変更:

    -	case b == 0:
    +	case base == 0:
    

    基数が0の場合(自動推測モード)の条件式で、bbase に変更されています。

    -			b = 16
    +			base = 16
    

    16進数プレフィックス("0x" または "0X")が検出された場合に、基数を16に設定する部分で、bbase に変更されています。

    -			b = 8
    +			base = 8
    

    8進数プレフィックス("0")が検出された場合に、基数を8に設定する部分で、bbase に変更されています。

    -			b = 10
    +			base = 10
    

    上記以外のデフォルトの場合に、基数を10に設定する部分で、bbase に変更されています。

  4. エラーメッセージの変更:

    -		err = errors.New("invalid base " + Itoa(b))
    +		err = errors.New("invalid base " + Itoa(base))
    

    無効な基数が指定された場合に生成されるエラーメッセージ内で、bbase に変更されています。

  5. cutoff64 関数の呼び出し:

    -	cutoff = cutoff64(b)
    +	cutoff = cutoff64(base)
    

    オーバーフローチェックに使用される cutoff64 関数に渡す引数が b から base に変更されています。

  6. 数値変換ロジックの変更:

    -	if int(v) >= b {
    +	if int(v) >= base {
    

    現在の桁の値 v が基数 base 以上であるかをチェックする部分で、bbase に変更されています。これは、例えば10進数で10以上の数字が出現した場合にエラーとするためのチェックです。

    -		// n*b overflows
    +		// n*base overflows
    

    コメントも n*b overflows から n*base overflows に変更され、コードとの整合性が保たれています。

    -	n *= uint64(b)
    +	n *= uint64(base)
    

    現在の解析中の数値 n に基数 base を掛ける部分で、bbase に変更されています。これは、次の桁を処理するために現在の数値をシフトする操作です。

これらの変更はすべて、ParseUint 関数内で b という名前で参照されていた基数パラメータを、より明確で一貫性のある base という名前に統一するためのものです。機能的な変更は一切なく、コードの可読性とAPIの一貫性のみを向上させています。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント (pkg.go.dev)
  • GitHubのGoリポジトリのコミット履歴
  • Go言語のコードレビューシステム (Gerrit)
  • 一般的なプログラミングにおける「基数」の概念に関する情報
  • Go言語のコーディング規約とベストプラクティスに関する情報 (Go Proverbsなど)