[インデックス 1197] ファイルの概要
このコミットは、Go言語の標準ライブラリmath
パッケージにおける大幅なリファクタリングとテストフレームワークの移行を目的としています。具体的には、math
パッケージ内の関数名をGoの慣習に従ってエクスポート可能な形式(先頭大文字)に変更し、変数宣言をより簡潔な形式(:=
演算子)に統一しています。また、カスタムのテストフレームワークからGo標準のtesting
パッケージへの移行が行われ、テストコードの構造と記述方法が改善されています。
コミット
commit 88daac7862531c606345787f2adff6cf845808d7
Author: Russ Cox <rsc@golang.org>
Date: Wed Nov 19 16:14:31 2008 -0800
gotestify & gostylify math.
R=r
DELTA=682 (275 added, 301 deleted, 106 changed)
OCL=19638
CL=19642
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/88daac7862531c606345787f2adff6cf845808d7
元コミット内容
gotestify & gostylify math.
このコミットメッセージは、「mathパッケージをテスト可能にし、Goのスタイルに合わせる」という意図を簡潔に示しています。gotestify
はテストの改善、gostylify
はGoのコーディング規約への準拠を意味すると考えられます。
変更の背景
このコミットが行われた2008年11月は、Go言語がまだ一般に公開される前の開発初期段階にあたります。Go言語は、その設計思想として「シンプルさ」「効率性」「並行処理」を重視しており、その一環としてコードの可読性や保守性を高めるための明確なコーディング規約(Go ProverbsやEffective Goとして後にまとめられるもの)が形成されつつありました。
変更の背景には、以下の点が挙げられます。
- Go言語の慣習の確立: Go言語では、関数や変数、型の名前の先頭文字が大文字か小文字かによって、その可視性(エクスポートされるか否か)が決定されます。このコミット以前は、
math
パッケージ内の多くの関数が小文字で始まっており、パッケージ外から直接利用できない状態でした。標準ライブラリとして提供されるべき数学関数群が、外部から利用できるようにエクスポートされる必要がありました。 - 標準テストフレームワークの採用: Go言語には、
testing
パッケージという組み込みのテストフレームワークが存在します。このコミット以前は、カスタムのテストユーティリティ(test/mathtest.go
に見られるck
関数など)が使用されていましたが、Go言語の成熟に伴い、標準のtesting
パッケージに移行することで、テストの記述、実行、レポート生成をより標準的かつ効率的に行うことが可能になります。これにより、開発者は一貫した方法でテストを記述し、Goのエコシステムが提供するツール(go test
コマンドなど)を最大限に活用できるようになります。 - コードの簡潔化と可読性向上:
var
キーワードを用いた冗長な変数宣言を、型推論を伴う短縮変数宣言:=
に置き換えることで、コードの記述量を減らし、可読性を向上させる狙いがあります。これはGo言語の設計哲学である「簡潔さ」に合致する変更です。 - パッケージインポートの整理:
import math "math"
のような冗長なパッケージエイリアスを削除し、import "math"
とすることで、コードの簡潔さを追求しています。
これらの変更は、Go言語が初期段階から、その設計思想に基づいた堅牢で一貫性のある標準ライブラリを構築しようとしていたことを示しています。
前提知識の解説
このコミットを理解するためには、以下のGo言語の基本的な概念を理解しておく必要があります。
-
Go言語の可視性ルール(Exported Names): Go言語では、パッケージ内の識別子(変数、関数、型、メソッドなど)の可視性は、その名前の先頭文字が大文字か小文字かによって決まります。
- 大文字で始まる識別子: パッケージ外からアクセス可能です(エクスポートされます)。これは他の言語における
public
に相当します。 - 小文字で始まる識別子: その識別子が定義されているパッケージ内からのみアクセス可能です(エクスポートされません)。これは他の言語における
private
やinternal
に相当します。 このコミットでは、asin
がAsin
に、atan
がAtan
にといった形で、多くの数学関数が小文字から大文字に名前が変更されており、これによりこれらの関数がmath
パッケージの外部から利用可能になっています。
- 大文字で始まる識別子: パッケージ外からアクセス可能です(エクスポートされます)。これは他の言語における
-
短縮変数宣言 (
:=
): Go言語では、変数を宣言し、同時に初期値を代入する際に、var
キーワードと型名を省略して:=
演算子を使用することができます。これは「短縮変数宣言」と呼ばれ、関数のローカル変数でよく使われます。 例:var x float64 = 10.0
はx := 10.0
と書くことができます。 このコミットでは、多くの場所でvar temp, x float64;
のような宣言がtemp, x := ...
のような形式に変更されています。 -
Go言語の
testing
パッケージ: Go言語には、ユニットテストやベンチマークテストを記述するための標準パッケージtesting
が用意されています。- テスト関数は
Test
で始まり、*testing.T
型の引数を一つ取ります(例:func TestFunctionName(t *testing.T)
)。 - テストの失敗を報告するには、
t.Error
やt.Errorf
などのメソッドを使用します。 - テストファイルは、テスト対象のソースファイルと同じディレクトリに配置され、ファイル名の末尾が
_test.go
である必要があります。 このコミットでは、カスタムのテストロジックから、この標準的なtesting
パッケージを利用したテストコードへの移行が行われています。
- テスト関数は
-
Go言語の慣用句(Idiomatic Go): Go言語には、コードの可読性、保守性、効率性を高めるための推奨されるコーディングスタイルやパターンが存在します。これらは「Goの慣用句」と呼ばれ、
Effective Go
などの公式ドキュメントで詳しく説明されています。関数名のエクスポートルールや短縮変数宣言の活用も、この慣用句の一部です。
技術的詳細
このコミットは、Go言語のsrc/lib/math
ディレクトリ内の複数のファイルにわたる広範な変更を含んでいます。主な技術的変更点は以下の通りです。
-
関数名の変更とエクスポート:
asin.go
,atan.go
,atan2.go
,exp.go
,fabs.go
,floor.go
,fmod.go
,hypot.go
,log.go
,pow.go
,pow10.go
,sin.go
,sinh.go
,sqrt.go
,tan.go
,tanh.go
といった全ての数学関数において、関数名の先頭文字が小文字から大文字に変更されました(例:asin
->Asin
)。これにより、これらの関数はmath
パッケージの外部から直接呼び出すことが可能になり、Goの標準ライブラリとしてのmath
パッケージの有用性が大幅に向上しました。 -
短縮変数宣言 (
:=
) の導入: 各関数の内部で、var
キーワードを用いて型を明示的に指定していた変数宣言の多くが、:=
演算子を用いた短縮変数宣言に置き換えられました。 例:var temp, x float64;
->var temp, x float64;
の行が削除され、temp, x := sys.modf(x);
のように初期化時に:=
が使用される。var argsq, value float64;
->argsq := arg*arg;
これは、コードの冗長性を減らし、より現代的でGoらしい記述スタイルへの移行を意味します。
-
パッケージインポートの簡潔化:
import math "math"
のように、パッケージ名とエイリアスが同じ場合にエイリアスを省略し、import "math"
と記述するように変更されました。これはGoの慣用句に従った変更であり、コードの簡潔さに貢献します。 -
テストフレームワークの全面的な移行:
- 既存のカスタムテストファイル
test/mathtest.go
が削除されました。このファイルは、fmt.sprintf
とpanic
を用いた独自のテスト検証ロジック(ck
関数)を持っていました。 - 新たに
src/lib/math/test.go
が追加されました。この新しいテストファイルは、Go標準のtesting
パッケージをインポートし、TestAsin
,TestAtan
などの標準的なテスト関数を定義しています。テストの検証にはt.Errorf
が使用され、期待値と実際の値が異なる場合にエラーを報告します。 - テストデータ(
vf
,asin
,atan
など)も、test/mathtest.go
からsrc/lib/math/test.go
に移動され、var
宣言からvar
宣言に変わっていますが、これはテストデータとしての配列の初期化方法の変更です。 この移行により、math
パッケージのテストはGoのエコシステムに完全に統合され、go test
コマンドで簡単に実行できるようになりました。また、testing
パッケージが提供する豊富な機能(テストの並列実行、ベンチマークなど)を活用できるようになります。
- 既存のカスタムテストファイル
-
細かなコードの最適化と修正:
fmod.go
のfmod
関数内で、r = x;
がr := x;
に変更され、sign
変数の初期化もsign := false;
に変更されています。hypot.go
のhypot
関数内で、r = p; p = q; q = r;
のような一時変数を使ったスワップが、Goの多重代入機能を使ったp, q = q, p;
に置き換えられています。sqrt.go
のsqrt
関数内で、ループの初期化がfor i=0; i<=4; i=i+1
からfor i:=0; i<=4; i++
に変更され、よりGoらしいイテレーションの記述になっています。
これらの変更は、Go言語の設計原則である「シンプルさ」「明瞭さ」「効率性」をmath
パッケージに適用し、Go言語の標準ライブラリとしての品質と使いやすさを向上させるための重要なステップでした。
コアとなるコードの変更箇所
このコミットにおけるコアとなるコードの変更は、主に以下の2つのパターンに集約されます。
-
関数名の変更(エクスポート):
src/lib/math
内の各ファイルで、export func
に続く関数名が小文字から大文字に変更されています。例1:
src/lib/math/asin.go
--- a/src/lib/math/asin.go +++ b/src/lib/math/asin.go @@ -4,7 +4,7 @@ package math -import math "math" +import "math" /* * asin(arg) and acos(arg) return the arcsin, arccos, @@ -18,9 +18,7 @@ const pio2 = .15707963267948966192313216e1 ) -export func -asin(arg float64)float64 -{\n +export func Asin(arg float64) float64 { var temp, x float64; var sign bool; @@ -34,11 +32,11 @@ asin(arg float64)float64 return sys.NaN(); } -\ttemp = sqrt(1 - x*x);\n +\ttemp = Sqrt(1 - x*x); if x > 0.7 {\n -\t\ttemp = pio2 - atan(temp/x);\n +\t\ttemp = pio2 - Atan(temp/x); } else {\n -\t\ttemp = atan(x/temp);\n +\t\ttemp = Atan(x/temp); } if sign {\n @@ -47,11 +45,9 @@ asin(arg float64)float64 return temp; } -export func -acos(arg float64)float64 -{\n +export func Acos(arg float64) float64 { if(arg > 1 || arg < -1) {\n return sys.NaN(); } -\treturn pio2 - asin(arg);\n +\treturn pio2 - Asin(arg); }
-
短縮変数宣言 (
:=
) の導入と冗長なvar
宣言の削除: 関数内部の変数宣言がvar
から:=
に置き換えられています。例2:
src/lib/math/exp.go
--- a/src/lib/math/exp.go +++ b/src/lib/math/exp.go @@ -4,7 +4,7 @@ package math -import math "math" +import "math" /* * exp returns the exponential func of its @@ -26,12 +26,7 @@ const maxf = 10000; ) -export func -exp(arg float64) float64 -{\n -\tvar x, fract, temp1, temp2, xsq float64;\n -\tvar ent int;\n -\n +export func Exp(arg float64) float64 { if arg == 0. {\n return 1; } @@ -42,11 +37,11 @@ exp(arg float64) float64 return sys.Inf(1) } -\tx = arg*log2e;\n -\tent = int(floor(x));\n -\tfract = (x-float64(ent)) - 0.5;\n -\txsq = fract*fract;\n -\ttemp1 = ((p2*xsq+p1)*xsq+p0)*fract;\n -\ttemp2 = ((xsq+q2)*xsq+q1)*xsq + q0;\n +\tx := arg*log2e; +\tent := int(Floor(x)); +\tfract := (x-float64(ent)) - 0.5; +\txsq := fract*fract; +\ttemp1 := ((p2*xsq+p3)*xsq+p2)*xsq+p1)*xsq+p0)*fract; +\ttemp2 := ((xsq+q2)*xsq+q1)*xsq + q0; return sys.ldexp(sqrt2*(temp2+temp1)/(temp2-temp1), ent); }
-
テストファイルの移動と標準
testing
パッケージへの移行:test/mathtest.go
が削除され、src/lib/math/test.go
が新規作成されています。例3:
src/lib/math/test.go
(新規ファイル)// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // $G $F.go && $L $F.$A && (./$A.out || echo BUG: math fails) package math import ( "math"; "testing"; ) // ... (テストデータとClose関数) ... export func TestAsin(t *testing.T) { for i := 0; i < len(vf); i++ { if f := math.Asin(vf[i]/10); !Close(asin[i], f) { t.Errorf("math.Asin(%g) = %g, want %g\n", vf[i]/10, f, asin[i]); } } } // ... (他のTest関数) ...
コアとなるコードの解説
このコミットのコアとなるコード変更は、Go言語の設計思想と慣習に深く根ざしています。
-
関数名のエクスポート: Go言語では、パッケージの外部から利用されるべき関数や型は、その名前を大文字で始める必要があります。この変更により、
math
パッケージ内のAsin
,Atan
,Exp
,Floor
,Log
,Pow
,Sin
,Sinh
,Sqrt
,Tan
,Tanh
,Fabs
,Ceil
,Fmod
,Hypot
,Log10
,Pow10
,Cos
といった主要な数学関数が、Goプログラムのどこからでもmath.Asin(...)
のように直接呼び出せるようになりました。これは、math
パッケージがGoの標準ライブラリとして機能するために不可欠な変更であり、Go言語のモジュール性と再利用性を高める上で極めて重要です。 -
短縮変数宣言 (
:=
) の活用:var
キーワードと型名を省略した:=
演算子による短縮変数宣言は、Go言語で推奨されるイディオムの一つです。これにより、コードがより簡潔になり、特にローカル変数の宣言と初期化が頻繁に行われる場合に、記述量を減らし、可読性を向上させます。コンパイラが型を推論するため、開発者は型の指定に煩わされることなく、ロジックに集中できます。この変更は、Go言語の「簡潔さ」という設計原則を体現しています。 -
標準
testing
パッケージへの移行:test/mathtest.go
で用いられていたカスタムのテストロジックは、Go言語が提供する標準のtesting
パッケージに置き換えられました。- 一貫性:
testing
パッケージを使用することで、Goプロジェクト全体でテストコードの記述方法に一貫性が生まれます。 - ツールとの統合:
go test
コマンドはtesting
パッケージと密接に連携しており、テストの発見、実行、結果のレポートを自動化します。これにより、開発ワークフローが効率化されます。 - 機能の拡張性:
testing
パッケージは、テストの並列実行、ベンチマークテスト、例(Example)テストなど、豊富な機能を提供します。カスタムテストフレームワークではこれらの機能を独自に実装する必要がありましたが、標準パッケージを利用することで、これらの恩恵を容易に享受できます。 この移行は、Go言語のテスト文化を確立し、開発者が信頼性の高いコードを効率的に書けるようにするための基盤を築きました。
- 一貫性:
これらの変更は、単なるコードの修正に留まらず、Go言語がその初期段階から、明確な設計原則と開発者の生産性を重視したエコシステムを構築しようとしていたことを強く示しています。
関連リンク
- Effective Go - Names: Go言語における名前付けの慣習、特にエクスポートされる名前について解説されています。
- The Go Programming Language Specification - Declarations and scope: Go言語の変数宣言とスコープに関する公式仕様。
- The Go Programming Language Specification - Short variable declarations: 短縮変数宣言
:=
に関する公式仕様。 - Go testing package documentation: Go標準の
testing
パッケージの公式ドキュメント。
参考にした情報源リンク
- GitHub: golang/go commit 88daac7862531c606345787f2adff6cf845808d7
- Go言語の公式ドキュメント(Effective Go, Language Specification,
testing
パッケージドキュメント) - Go言語の可視性ルールに関する一般的な知識
- Go言語の短縮変数宣言に関する一般的な知識
- Go言語のテストに関する一般的な知識
- コミットメッセージと差分からの直接的なコード分析