[インデックス 16476] ファイルの概要
このコミットは、Go言語のドキュメントとサンプルコードにおいて、Cgo(GoとC言語の相互運用機能)に関する記事で使用されているC標準ライブラリの乱数生成関数を、より移植性の高いC90標準の関数に修正するものです。具体的には、random()
と srandom()
を rand()
と srand()
に置き換えています。
コミット
commit 022818c142ebc62da9a0e3a86c728ab36c047027
Author: Shenghou Ma <minux.ma@gmail.com>
Date: Tue Jun 4 01:40:53 2013 +0800
doc/articles: use C90 standard functions in the cgo article.
R=golang-dev, iant
CC=golang-dev
https://golang.org/cl/9953043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/022818c142ebc62da9a0e3a86c728ab36c047027
元コミット内容
doc/articles: use C90 standard functions in the cgo article.
変更の背景
この変更の背景には、C言語の標準ライブラリ関数における移植性の問題があります。random()
と srandom()
関数は、主にBSD系(Unix-like)システムで利用される乱数生成関数であり、POSIX標準の一部ではありますが、C90(ANSI C)標準には含まれていません。一方、rand()
と srand()
関数はC90標準で定義されており、より広範なシステムで利用可能です。
Go言語のドキュメント、特にCgoに関する記事は、GoとC言語の連携方法を説明する上で、可能な限り多くの環境で動作する汎用的な例を提供することが重要です。random()
と srandom()
を使用した例は、Windowsなどの非Unix系システムや、古いCコンパイラ環境ではコンパイルエラーやリンクエラーを引き起こす可能性がありました。
このコミットは、ドキュメントの正確性と移植性を向上させ、より多くの読者がCgoの例を自身の環境で試せるようにするために行われました。これにより、Go言語の学習者がCgoの概念を理解する上で、環境依存の問題に遭遇する可能性を減らすことができます。
前提知識の解説
Cgo
Cgoは、GoプログラムからC言語のコードを呼び出すためのGo言語の機能です。Goのソースファイル内にC言語のコードを直接記述したり、既存のCライブラリをリンクしたりすることができます。Cgoを使用することで、Go言語では実装が難しい低レベルの操作や、既存のC言語資産の再利用が可能になります。
Cgoでは、C言語の関数や型は C
パッケージを通じてアクセスされます。例えば、C言語の rand()
関数を呼び出すには C.rand()
と記述します。また、C言語の型とGo言語の型の間で変換が必要になる場合があります(例: C.uint(i)
)。
C言語の乱数生成関数
C言語には、主に2種類の擬似乱数生成関数群が存在します。
-
rand()
とsrand()
(C90標準)rand()
: 擬似乱数を生成し、0
からRAND_MAX
までの整数を返します。RAND_MAX
は<stdlib.h>
で定義されるマクロで、最低でも32767です。srand(unsigned int seed)
:rand()
が生成する乱数列のシード(初期値)を設定します。同じシード値を与えると、常に同じ乱数列が生成されます。通常、異なる乱数列を得るために、プログラムの起動時に一度だけtime(NULL)
などをシードとして使用します。- 特徴: C90標準で定義されており、非常に高い移植性を持っています。しかし、生成される乱数の品質(統計的特性)は、
random()
に比べて劣るとされることがあります。特に、下位ビットのランダム性が低い、周期が短いといった問題が指摘されることがあります。
-
random()
とsrandom()
(POSIX/BSD拡張)random()
: 擬似乱数を生成し、long
型の値を返します。rand()
よりも広い範囲の値を生成し、一般的にrand()
よりも高品質な乱数を生成するとされています。srandom(unsigned int seed)
:random()
が生成する乱数列のシードを設定します。- 特徴: POSIX標準の一部であり、Unix-likeシステム(Linux, macOS, BSDなど)で広く利用されています。しかし、Windowsなどのシステムでは標準で提供されていないため、移植性に欠けます。
このコミットは、Goのドキュメントの例が、より多くの環境で動作するように、移植性の高い rand()
と srand()
を採用したものです。
技術的詳細
このコミットの技術的な変更点は、Go言語のCgoに関するドキュメントと、それに付随するサンプルコードにおいて、C言語の乱数生成関数の呼び出しを random
/srandom
から rand
/srand
へと変更したことです。
具体的には、以下のファイルが変更されています。
doc/articles/c_go_cgo.html
: Cgoに関する記事のHTMLファイル。doc/progs/cgo1.go
: Cgoのサンプルコード1。doc/progs/cgo2.go
: Cgoのサンプルコード2。
HTMLドキュメントでは、Cgoの例としてC言語の乱数生成関数をGoから呼び出す方法が説明されています。この説明文中で参照されている関数名が random
から rand
へ、srandom
から srand
へと変更されました。また、random
関数が long
型の値を返すという記述が、rand
関数が int
型の値を返すという記述に修正されています。これは、C90標準の rand()
関数が int
を返すのに対し、POSIXの random()
関数が long
を返すという違いを反映したものです。
Goのサンプルコード (cgo1.go
と cgo2.go
) では、実際にC言語の関数を呼び出す部分が修正されました。C.random()
は C.rand()
に、C.srandom()
は C.srand()
に変更されています。また、cgo2.go
では C.long
型の変数 r
が C.int
型に変更されています。これは、Goの int
型に変換する前に、C言語側で受け取る値の型を正確に反映させるためです。
これらの変更により、ドキュメントの記述とサンプルコードがC90標準に準拠し、より多くのプラットフォームでの互換性が確保されました。
コアとなるコードの変更箇所
doc/articles/c_go_cgo.html
--- a/doc/articles/c_go_cgo.html
+++ b/doc/articles/c_go_cgo.html
@@ -11,8 +11,8 @@ single Go package.
<p>
To lead with an example, here's a Go package that provides two functions -
-<code>Random</code> and <code>Seed</code> - that wrap C's <code>random</code>
-and <code>srandom</code> functions.
+<code>Random</code> and <code>Seed</code> - that wrap C's <code>rand</code>
+and <code>srand</code> functions.
</p>
{{code "/doc/progs/cgo1.go" `/package rand/` `/END/`}}
@@ -30,14 +30,14 @@ name space.
<p>
The <code>rand</code> package contains four references to the <code>C</code>
-package: the calls to <code>C.random</code> and <code>C.srandom</code>, the
+package: the calls to <code>C.rand</code> and <code>C.srand</code>, the
conversion <code>C.uint(i)</code>, and the <code>import</code> statement.
</p>
<p>
The <code>Random</code> function calls the standard C library's <code>random</code>
-function and returns the result. In C, <code>random</code> returns a value of the
-C type <code>long</code>, which cgo represents as the type <code>C.long</code>.
+function and returns the result. In C, <code>rand</code> returns a value of the
+C type <code>int</code>, which cgo represents as the type <code>C.int</code>.
It must be converted to a Go type before it can be used by Go code outside this
package, using an ordinary Go type conversion:
</p>
@@ -54,7 +54,7 @@ the type conversion more explicitly:
<p>
The <code>Seed</code> function does the reverse, in a way. It takes a
regular Go <code>int</code>, converts it to the C <code>unsigned int</code>
-type, and passes it to the C function <code>srandom</code>.
+type, and passes it to the C function <code>srand</code>.
</p>
{{code "/doc/progs/cgo1.go" `/func Seed/` `/END/`}}
doc/progs/cgo1.go
--- a/doc/progs/cgo1.go
+++ b/doc/progs/cgo1.go
@@ -12,12 +12,12 @@ import "C"
// STOP OMIT
func Random() int {
- return int(C.random())
+ return int(C.rand())
}
// STOP OMIT
func Seed(i int) {
- C.srandom(C.uint(i))
+ C.srand(C.uint(i))
}
// END OMIT
doc/progs/cgo2.go
--- a/doc/progs/cgo2.go
+++ b/doc/progs/cgo2.go
@@ -11,13 +11,13 @@ package rand2
import "C"
func Random() int {
- var r C.long = C.random()
+ var r C.int = C.rand()
return int(r)
}
// STOP OMIT
func Seed(i int) {
- C.srandom(C.uint(i))
+ C.srand(C.uint(i))
}
// END OMIT
コアとなるコードの解説
doc/articles/c_go_cgo.html
の変更点
- 関数名の変更:
C's random and srandom functions
がC's rand and srand functions
に変更されました。これは、記事内で説明されているCgoの例が、どのC関数をラップしているかを明確にするためです。
- Cgo呼び出しの記述変更:
calls to C.random and C.srandom
がcalls to C.rand and C.srand
に変更されました。これは、Goコード内でのC関数呼び出しの記述を修正したものです。
- 戻り値の型の説明変更:
In C, random returns a value of the C type long, which cgo represents as the type C.long.
がIn C, rand returns a value of the C type int, which cgo represents as the type C.int.
に変更されました。これは、random()
とrand()
の戻り値の型が異なる(long
vsint
)ことを正確に反映させるための重要な修正です。Cgoでは、C言語の型とGo言語の型の間で適切なマッピングが行われるため、この記述の正確性は重要です。
Seed
関数の引数の説明変更:passes it to the C function srandom
がpasses it to the C function srand
に変更されました。
これらの変更は、ドキュメントの内容を実際のコードの変更と一致させ、読者に正確な情報を提供することを目的としています。
doc/progs/cgo1.go
および doc/progs/cgo2.go
の変更点
両方のGoファイルで、C言語の乱数生成関数を呼び出す部分が修正されています。
Random()
関数内:return int(C.random())
がreturn int(C.rand())
に変更されました。これにより、GoのRandom
関数がC90標準のrand()
関数を呼び出すようになります。
Seed()
関数内:C.srandom(C.uint(i))
がC.srand(C.uint(i))
に変更されました。これにより、GoのSeed
関数がC90標準のsrand()
関数を呼び出すようになります。
doc/progs/cgo2.go
の追加変更:var r C.long = C.random()
がvar r C.int = C.rand()
に変更されました。これは、random()
がlong
を返すのに対し、rand()
がint
を返すため、Cgoで受け取る変数の型をC.long
からC.int
に修正したものです。この変更は、C言語の型とGo言語の型の間での正確な型変換を保証するために必要です。
これらのコード変更により、GoのCgoサンプルプログラムが、より移植性の高いC90標準の乱数生成関数を使用するようになり、異なるオペレーティングシステムやコンパイラ環境での互換性が向上しました。
関連リンク
- Go言語のCgoに関する公式ドキュメント: https://go.dev/cmd/cgo/
- Go言語のブログ記事「Go and Cgo」: https://go.dev/blog/cgo (このコミットで修正された記事の元となる可能性のある記事)
参考にした情報源リンク
- C言語
rand()
とsrand()
のドキュメント (cppreference.com): https://en.cppreference.com/w/c/numeric/rand - C言語
random()
とsrandom()
のドキュメント (POSIX): https://pubs.opengroup.org/onlinepubs/9699919799/functions/random.html - Stack Overflow:
rand()
vsrandom()
: https://stackoverflow.com/questions/10002087/rand-vs-random - Stack Overflow:
rand()
vsrandom()
in C: https://stackoverflow.com/questions/10002087/rand-vs-random (Web検索結果で参照されたもの) - Wikipedia: C standard library (stdlib.h): https://en.wikipedia.org/wiki/C_standard_library#stdlib.h
- C90 (ANSI C) standard: https://en.wikipedia.org/wiki/ANSI_C