[インデックス 10621] ファイルの概要
このコミットは、Go言語のソースコード内のコメントおよびドキュメントにおいて、「キャスト (cast)」という用語を「変換 (convert)」という用語に統一する変更を行っています。具体的には、src/pkg/compress/bzip2/bit_reader.go
、src/pkg/exp/ssh/session_test.go
、src/pkg/fmt/doc.go
、src/pkg/unicode/graphic.go
の4つのファイルが影響を受けています。
コミット
- コミットハッシュ:
0a5508c69238e9f68faff2747a1abe9cbdb10dd6
- 作者: Rob Pike r@golang.org
- 日付: Mon Dec 5 19:40:52 2011 -0800
- コミットメッセージ:
various: we don't cast, we convert R=golang-dev, dsymonds CC=golang-dev https://golang.org/cl/5437142
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/0a5508c69238e9f68faff2747a1abe9cbdb10dd6
元コミット内容
commit 0a5508c69238e9f68faff2747a1abe9cbdb10dd6
Author: Rob Pike <r@golang.org>
Date: Mon Dec 5 19:40:52 2011 -0800
various: we don't cast, we convert
R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/5437142
---
src/pkg/compress/bzip2/bit_reader.go | 2 +-\n src/pkg/exp/ssh/session_test.go | 2 +-\n src/pkg/fmt/doc.go | 2 +-\n src/pkg/unicode/graphic.go | 4 ++--
4 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/pkg/compress/bzip2/bit_reader.go b/src/pkg/compress/bzip2/bit_reader.go
index b2c13e50ca..b35c69a1cc 100644
--- a/src/pkg/compress/bzip2/bit_reader.go
+++ b/src/pkg/compress/bzip2/bit_reader.go
@@ -20,7 +20,7 @@ type bitReader struct {
err error
}
-// bitReader needs to read bytes from an io.Reader. We attempt to cast the
+// bitReader needs to read bytes from an io.Reader. We attempt to convert the
// given io.Reader to this interface and, if it doesn't already fit, we wrap in
// a bufio.Reader.
type byteReader interface {
diff --git a/src/pkg/exp/ssh/session_test.go b/src/pkg/exp/ssh/session_test.go
index 4be7746d17..d4818c29f7 100644
--- a/src/pkg/exp/ssh/session_test.go
+++ b/src/pkg/exp/ssh/session_test.go
@@ -61,7 +61,7 @@ func dial(t *testing.T) *ClientConn {
WantReply bool
Status uint32
}
- // TODO(dfc) casting to the concrete type should not be
+ // TODO(dfc) converting to the concrete type should not be
// necessary to send a packet.
msg := exitMsg{
PeersId: ch.(*channel).theirId,
diff --git a/src/pkg/fmt/doc.go b/src/pkg/fmt/doc.go
index 747865c6f9..11e9f19f89 100644
--- a/src/pkg/fmt/doc.go
+++ b/src/pkg/fmt/doc.go
@@ -103,7 +103,7 @@
To avoid recursion in cases such as
type X string
func (x X) String() string { return Sprintf("<%s>", x) }
- cast the value before recurring:
+ convert the value before recurring:
func (x X) String() string { return Sprintf("<%s>", string(x)) }
Format errors:
diff --git a/src/pkg/unicode/graphic.go b/src/pkg/unicode/graphic.go
index 9343bc9b0a..2904da6c6d 100644
--- a/src/pkg/unicode/graphic.go
+++ b/src/pkg/unicode/graphic.go
@@ -32,8 +32,8 @@ var PrintRanges = []*RangeTable{\n // Such characters include letters, marks, numbers, punctuation, symbols, and\n // spaces, from categories L, M, N, P, S, Zs.\n func IsGraphic(r rune) bool {\n- // We cast to uint32 to avoid the extra test for negative,\n- // and in the index we cast to uint8 to avoid the range check.\n+ // We convert to uint32 to avoid the extra test for negative,\n+ // and in the index we convert to uint8 to avoid the range check.\n if uint32(r) <= MaxLatin1 {\n return properties[uint8(r)]&pg != 0
}
変更の背景
このコミットの背景には、Go言語の設計哲学と、型システムにおける用語の厳密性へのこだわりがあります。多くのプログラミング言語、特にCやC++のような言語では、「キャスト (cast)」という用語は、ある型の値を別の型として「解釈し直す」操作を指すことが一般的です。これは、多くの場合、メモリ上のビットパターンをそのまま別の型として扱うことを意味し、データ表現の変更を伴わないか、あるいは危険な再解釈を伴うことがあります。
しかし、Go言語の型システムでは、このような「キャスト」の概念は存在しません。Goにおける型間の操作は、常に「変換 (conversion)」として扱われます。Goの「変換」は、ある型の値を別の型の新しい値として生成する操作であり、元の値のビットパターンを単に再解釈するのではなく、新しい型の規則に従って新しい値を構築します。例えば、int
からfloat64
への変換は、単にビットを再解釈するのではなく、整数値を浮動小数点数表現に変換する計算を伴います。
このコミットは、Go言語の公式ドキュメント、コメント、およびコードベース全体で、この重要な区別を明確にするための取り組みの一環です。不正確な用語の使用は、特にGo言語を学び始めた開発者にとって混乱を招く可能性があり、Goの型システムの正確な理解を妨げる恐れがあります。Rob Pike氏(Go言語の共同設計者の一人)によるこの変更は、言語の設計意図を正確に反映し、一貫性のある用語法を確立することを目的としています。
前提知識の解説
このコミットの意図を理解するためには、以下の前提知識が役立ちます。
1. 型システムにおける「キャスト」と「変換」の違い
-
キャスト (Casting):
- 主にC/C++のような言語で用いられる概念。
- ある型の値を、メモリ上のビットパターンを再解釈することで、別の型として扱う操作。
- 多くの場合、新しい値は生成されず、既存のメモリ領域が異なる型として参照される。
- 例:
(int*)ptr
は、ptr
が指すメモリをint
型のポインタとして解釈し直す。 - 危険を伴うことがあり、未定義動作を引き起こす可能性もある。
-
変換 (Conversion):
- Go言語を含む多くの現代的な言語で用いられる概念。
- ある型の値を、別の型の新しい値として生成する操作。
- 元の値のデータが、新しい型の規則に従って適切に変換される。
- 例:
float64(myInt)
は、myInt
というint
型の値から、対応するfloat64
型の新しい値を生成する。 - 型安全性が高く、予期せぬ動作が少ない。
2. Go言語の型システム
Go言語は静的型付け言語であり、厳格な型システムを持っています。
- 明示的な変換: Goでは、異なる型間の変換はほとんどの場合、明示的に行う必要があります。例えば、
int
型の変数をfloat64
型として使用するには、float64(myInt)
のように明示的な変換が必要です。 - 暗黙的な変換の欠如: Goには、C/C++のような暗黙的な型変換(例えば、
int
とfloat
の混合演算でint
が自動的にfloat
に変換されるなど)はほとんど存在しません。これにより、予期せぬ型変換によるバグを防ぎ、コードの意図を明確にします。 - インターフェース型: Goのインターフェース型は、ポリモーフィズムを実現するための強力な機能です。具体的な型がインターフェースを満たす場合、その具体的な型の値をインターフェース型として扱うことができます。これは「型アサーション (type assertion)」や「型スイッチ (type switch)」を通じて行われますが、これも「変換」の一種と見なすことができます。
3. 用語の統一の重要性
プログラミング言語のドキュメントやコードベースにおける用語の統一は、以下の点で非常に重要です。
- 学習曲線: 新しい言語を学ぶ開発者にとって、正確で一貫した用語は理解を助け、混乱を減らします。
- コードの可読性: コード内のコメントや変数名が言語の概念と一致していると、コードの意図がより明確になります。
- コミュニティの共通理解: 正しい用語が使われることで、開発者コミュニティ全体で共通の理解が形成され、議論や情報共有がスムーズになります。
技術的詳細
このコミットは、Go言語のソースコード内のコメントやドキュメントにおける「cast」という単語を「convert」に置き換えるという、一見すると些細な変更に見えますが、Go言語の型システムにおける根本的な哲学を反映した重要な修正です。
Go言語では、ある型の値を別の型として扱う場合、それは常に「変換 (conversion)」として行われます。これは、元の値のビットパターンを単に再解釈する「キャスト」とは異なり、新しい型の規則に従って新しい値を生成する操作です。例えば、int
型のx
をfloat64
型に変換する場合、float64(x)
と記述しますが、これはx
の整数値を浮動小数点数表現に変換した新しいfloat64
型の値を生成します。メモリ上のx
のビットがそのままfloat64
として解釈されるわけではありません。
この厳密な用語の使い分けは、Go言語が型安全性を重視し、開発者がコードの挙動を正確に理解できるようにするための設計思想に基づいています。C/C++のような言語の「キャスト」は、時に危険な操作であり、メモリの再解釈によって予期せぬバグやセキュリティ脆弱性を引き起こす可能性があります。Goはこのような曖昧さや危険性を排除するために、明示的な「変換」のみを許可し、その操作が常に新しい値を生成することを保証します。
このコミットによって、Goの公式なコードベースやドキュメントにおいて、この「キャスト」と「変換」の区別がより明確にされ、Go言語の型システムに対する正確な理解が促進されます。これは、特に他の言語の経験を持つ開発者がGoに移行する際に、誤解を避ける上で非常に役立ちます。
コアとなるコードの変更箇所
このコミットでは、以下の4つのファイルで「cast」という単語が「convert」に置き換えられています。
src/pkg/compress/bzip2/bit_reader.go
--- a/src/pkg/compress/bzip2/bit_reader.go
+++ b/src/pkg/compress/bzip2/bit_reader.go
@@ -20,7 +20,7 @@ type bitReader struct {
err error
}
-// bitReader needs to read bytes from an io.Reader. We attempt to cast the
+// bitReader needs to read bytes from an io.Reader. We attempt to convert the
// given io.Reader to this interface and, if it doesn't already fit, we wrap in
// a bufio.Reader.
type byteReader interface {
src/pkg/exp/ssh/session_test.go
--- a/src/pkg/exp/ssh/session_test.go
+++ b/src/pkg/exp/ssh/session_test.go
@@ -61,7 +61,7 @@ func dial(t *testing.T) *ClientConn {
WantReply bool
Status uint32
}
- // TODO(dfc) casting to the concrete type should not be
+ // TODO(dfc) converting to the concrete type should not be
// necessary to send a packet.
msg := exitMsg{
PeersId: ch.(*channel).theirId,
src/pkg/fmt/doc.go
--- a/src/pkg/fmt/doc.go
+++ b/src/pkg/fmt/doc.go
@@ -103,7 +103,7 @@
To avoid recursion in cases such as
type X string
func (x X) String() string { return Sprintf("<%s>", x) }
- cast the value before recurring:
+ convert the value before recurring:
func (x X) String() string { return Sprintf("<%s>", string(x)) }
Format errors:
src/pkg/unicode/graphic.go
--- a/src/pkg/unicode/graphic.go
+++ b/src/pkg/unicode/graphic.go
@@ -32,8 +32,8 @@ var PrintRanges = []*RangeTable{\n // Such characters include letters, marks, numbers, punctuation, symbols, and\n // spaces, from categories L, M, N, P, S, Zs.\n func IsGraphic(r rune) bool {\n- // We cast to uint32 to avoid the extra test for negative,\n- // and in the index we cast to uint8 to avoid the range check.\n+ // We convert to uint32 to avoid the extra test for negative,\n+ // and in the index we convert to uint8 to avoid the range check.\n if uint32(r) <= MaxLatin1 {\n return properties[uint8(r)]&pg != 0
}
コアとなるコードの解説
各ファイルの変更は、Go言語における型操作の正確な表現を目的としています。
-
src/pkg/compress/bzip2/bit_reader.go
:- 変更前:
// bitReader needs to read bytes from an io.Reader. We attempt to cast the
- 変更後:
// bitReader needs to read bytes from an io.Reader. We attempt to convert the
- 解説:
io.Reader
インターフェースから具体的なbyteReader
インターフェースへの操作について言及しています。Goでは、インターフェース型から具体的な型への「型アサーション」も、概念的には「変換」の一種と捉えられます。ここでは、io.Reader
がbyteReader
インターフェースを満たすかどうかをチェックし、満たさない場合はbufio.Reader
でラップするという文脈で、「キャスト」ではなく「変換」がより正確な表現となります。
- 変更前:
-
src/pkg/exp/ssh/session_test.go
:- 変更前:
// TODO(dfc) casting to the concrete type should not be
- 変更後:
// TODO(dfc) converting to the concrete type should not be
- 解説: SSHセッションのテストコードにおけるコメントです。
ch.(*channel)
のように、インターフェース型ch
を具体的な型*channel
に型アサーションする操作について言及しています。これもまた、Goの文脈では「キャスト」ではなく「変換」と表現するのが適切です。
- 変更前:
-
src/pkg/fmt/doc.go
:- 変更前:
cast the value before recurring:
- 変更後:
convert the value before recurring:
- 解説:
fmt
パッケージのドキュメントにおける、String()
メソッドの再帰を防ぐためのアドバイスです。type X string
のようなカスタム型がSprintf
内で再帰的にString()
メソッドを呼び出すのを避けるために、string(x)
のように基底型に「変換」してから渡すことを推奨しています。ここでのstring(x)
は、X
型の値をstring
型の新しい値に変換する操作であり、まさに「変換」です。
- 変更前:
-
src/pkg/unicode/graphic.go
:- 変更前:
// We cast to uint32 to avoid the extra test for negative,
- 変更後:
// We convert to uint32 to avoid the extra test for negative,
- 変更前:
// and in the index we cast to uint8 to avoid the range check.
- 変更後:
// and in the index we convert to uint8 to avoid the range check.
- 解説: Unicodeの文字がグラフィック文字であるかを判定する
IsGraphic
関数内のコメントです。rune
型(Goではint32
のエイリアス)の値をuint32
やuint8
に変換する操作について言及しています。これらの操作は、符号なし整数型への明示的な型変換であり、Goの定義する「変換」に該当します。負の値のチェックを避けるため、あるいは配列のインデックスとして使用する際に範囲チェックを避けるために行われるこれらの操作は、新しい型の値を生成する「変換」として正確に記述されるべきです。
- 変更前:
これらの変更は、Go言語の設計思想と型システムの厳密性を反映し、コードベース全体の用語の一貫性と正確性を高めることを目的としています。
関連リンク
- Go CL 5437142: https://golang.org/cl/5437142
参考にした情報源リンク
- Go言語の公式ドキュメント (型変換に関するセクション): https://go.dev/ref/spec#Conversions
- Go言語の型システムに関する議論 (Stack Overflow, Go Forumなど)
- Casting vs. Converting in Go: https://stackoverflow.com/questions/11343007/casting-vs-converting-in-go (一般的な理解を深めるために参照)
- Go言語の設計哲学に関する記事やブログポスト (Rob Pike氏の講演など)