[インデックス 14364] ファイルの概要
このコミットは、Go言語のテストスイート内の test/index.go
ファイルに対する変更です。具体的には、int
型のサイズに関するテストロジックが修正されています。
コミット
commit 3e50372f1ff0229aa8c42cde8f5cd0b6357b605d
Author: Ian Lance Taylor <iant@golang.org>
Date: Thu Nov 8 15:43:28 2012 -0800
test: change index.go to test size of int, not GOARCH == "amd64"
Fixes the test to work correctly on other platforms with
64-bit ints, like Alpha.
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/6822099
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/3e50372f1ff0229aa8c42cde8f5cd0b6357b605d
元コミット内容
このコミットの目的は、test/index.go
内のテストが、特定のアーキテクチャ(amd64
)に依存するのではなく、int
型の実際のサイズに基づいて動作するように修正することです。これにより、Alphaプロセッサのような64ビットint
を持つ他のプラットフォームでもテストが正しく機能するようになります。
変更の背景
Go言語はクロスプラットフォーム対応を重視しており、様々なアーキテクチャで動作するように設計されています。以前の test/index.go
のテストコードでは、int
型のサイズが64ビットであるかどうかを runtime.GOARCH == "amd64"
という条件で判断していました。しかし、これは amd64
アーキテクチャが64ビットシステムであるという一般的な仮定に基づいています。
問題は、amd64
以外のアーキテクチャでも int
型が64ビットである場合があることです。例えば、Alphaプロセッサは64ビットアーキテクチャであり、その上でGoが動作する場合、int
型も64ビットになります。このような環境では、runtime.GOARCH == "amd64"
という条件は偽となるため、int
型のサイズが64ビットであるにもかかわらず、テストが意図したパスを通らない、あるいは誤った結果を出す可能性がありました。
このコミットは、このようなアーキテクチャ依存の問題を解決し、テストの移植性と正確性を向上させるために行われました。
前提知識の解説
- Go言語の
int
型: Go言語のint
型は、その実行環境のCPUアーキテクチャに依存してサイズが変わる整数型です。32ビットシステムでは32ビット(4バイト)、64ビットシステムでは64ビット(8バイト)のサイズを持ちます。これは、C言語のint
型が通常32ビットであるのとは異なり、Go言語の設計思想の一つです。 runtime.GOARCH
: Go言語のruntime
パッケージに含まれる変数で、現在のプログラムが実行されているシステムのアーキテクチャ(例: "amd64", "arm", "386" など)を示す文字列を返します。unsafe.Sizeof
: Go言語のunsafe
パッケージに含まれる関数で、任意の型の変数がメモリ上で占めるバイト数を返します。これはコンパイル時に評価される定数です。unsafe
パッケージは、Goの型安全性を迂回する低レベルな操作を可能にするため、通常は注意して使用されますが、このようなシステムレベルの情報を取得する際には有用です。- コンパイル時エラーと実行時エラー: プログラミングにおいて、エラーは大きく分けてコンパイル時と実行時に発生します。
- コンパイル時エラー: ソースコードが言語の文法規則や型規則に違反している場合に、コンパイラがプログラムをビルドする際に検出するエラーです。例えば、存在しない変数を参照したり、型が一致しない演算を行ったりする場合などです。
- 実行時エラー: プログラムが正常にコンパイルされ、実行された後に発生するエラーです。例えば、ゼロ除算、配列の範囲外アクセス、メモリ不足などです。
- Go言語における大きな数値リテラル: Go言語では、整数リテラルが
int
型の最大値を超える場合、通常はコンパイル時エラーとなります。しかし、int
型が64ビットである環境では、32ビット環境では大きすぎると判断される数値リテラルでもint
型に収まるため、コンパイルエラーにならずに処理されることがあります。このコミットで修正されているテストは、この挙動を検証するものです。
技術的詳細
変更前のコードでは、i == "i64big" || i == "i64bigger"
という条件(これは非常に大きな整数リテラルをテストしていることを示唆しています)と runtime.GOARCH == "amd64"
という条件がAND結合されていました。これは、「もし amd64
アーキテクチャであれば、これらの大きな数値は int
に収まるため、コンパイル時に拒否されない」という仮定に基づいています。
しかし、この仮定は amd64
以外の64ビットアーキテクチャ(例: Alpha)では破綻します。これらのプラットフォームでは int
型が64ビットであるため、i64big
や i64bigger
といった大きな数値リテラルも int
に収まりますが、runtime.GOARCH == "amd64"
は偽となるため、テストのロジックが正しく適用されませんでした。
このコミットでは、runtime.GOARCH == "amd64"
を unsafe.Sizeof(int(0)) > 4
に変更しています。
int(0)
はint
型のゼロ値です。unsafe.Sizeof(int(0))
は、int
型がメモリ上で占めるバイト数を返します。> 4
という条件は、int
型のサイズが4バイト(32ビット)よりも大きい、つまり8バイト(64ビット)であることを意味します。
この変更により、テストは特定のアーキテクチャ名に依存するのではなく、int
型の実際のサイズに基づいて動作するようになります。これにより、amd64
であろうとAlphaであろうと、int
型が64ビットであるすべてのプラットフォームでテストが正しく機能するようになります。これは、Go言語の移植性を高める上で重要な修正です。
コアとなるコードの変更箇所
--- a/test/index.go
+++ b/test/index.go
@@ -13,7 +13,7 @@ import (
"bufio"
"fmt"
"os"
- "runtime"
+ "unsafe"
)
const prolog = `
@@ -214,9 +214,10 @@ func main() {
// the next pass from running.
// So run it as a separate check.
thisPass = 1
- } else if a == "s" && n == "" && (i == "i64big" || i == "i64bigger") && runtime.GOARCH == "amd64" {
- // On amd64, these huge numbers do fit in an int, so they are not
- // rejected at compile time.
+ } else if a == "s" && n == "" && (i == "i64big" || i == "i64bigger") && unsafe.Sizeof(int(0)) > 4 {
+ // If int is 64 bits, these huge
+ // numbers do fit in an int, so they
+ // are not rejected at compile time.
thisPass = 0
} else {
thisPass = 2
コアとなるコードの解説
変更は test/index.go
ファイルの main
関数内の条件分岐にあります。
-
変更前:
} else if a == "s" && n == "" && (i == "i64big" || i == "i64bigger") && runtime.GOARCH == "amd64" { // On amd64, these huge numbers do fit in an int, so they are not // rejected at compile time. thisPass = 0
この行では、
a == "s"
とn == ""
と(i == "i64big" || i == "i64bigger")
という条件に加えて、runtime.GOARCH == "amd64"
というアーキテクチャ固有のチェックが行われていました。コメントにもあるように、amd64
環境では大きな数値リテラルがint
に収まるため、コンパイルエラーにならないことを期待していました。 -
変更後:
} else if a == "s" && n == "" && (i == "i64big" || i == "i64bigger") && unsafe.Sizeof(int(0)) > 4 { // If int is 64 bits, these huge // numbers do fit in an int, so they // are not rejected at compile time. thisPass = 0
runtime.GOARCH == "amd64"
の部分がunsafe.Sizeof(int(0)) > 4
に置き換えられました。これにより、テストの条件が「現在のシステムでint
型が64ビット(4バイトより大きい)であるか」という、より汎用的なものになりました。この変更により、amd64
以外の64ビットアーキテクチャでも、このテストパスが正しく評価されるようになります。
また、この変更に伴い、runtime
パッケージのインポートが不要になり、代わりに unsafe
パッケージがインポートされています。
関連リンク
- Go言語の
int
型の仕様に関する公式ドキュメント: https://go.dev/ref/spec#Numeric_types runtime
パッケージのドキュメント: https://pkg.go.dev/runtimeunsafe
パッケージのドキュメント: https://pkg.go.dev/unsafe
参考にした情報源リンク
- Go言語の公式ドキュメント
- Go言語のソースコードリポジトリ (GitHub)
- Go言語のIssueトラッカーおよびコードレビューシステム (Gerrit)
- 一般的なプログラミングにおけるコンパイル時と実行時の概念に関する情報