[インデックス 10684] ファイルの概要
このコミットは、Go言語の仕様書である doc/go_spec.html
ファイルに対する変更です。具体的には、Go言語における型なし(untyped)の真偽値(boolean)定数と文字列(string)定数に関する記述を修正し、より正確な例を追加しています。
コミット
commit ef1c5357277f66d71e127e954991d4342da8c5c7
Author: Russ Cox <rsc@golang.org>
Date: Fri Dec 9 00:13:19 2011 -0500
spec: examples of untyped boolean, string constants
This is a spec correction, not a language change.
The implementations have behaved like this for years
(and there are tests to that effect), and elsewhere in
the spec true and false are defined to be untyped
boolean constants.
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5477047
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/ef1c5357277f66d71e127e954991d4342da8c5c7
元コミット内容
spec: examples of untyped boolean, string constants
This is a spec correction, not a language change.
The implementations have behaved like this for years
(and there are tests to that effect), and elsewhere in
the spec true and false are defined to be untyped
boolean constants.
変更の背景
このコミットの背景は、Go言語の仕様書(spec)が、実際の言語実装の振る舞いや、仕様書の他の箇所での定義と整合していなかった点にあります。具体的には、真偽値定数(true
やfalse
)や文字列定数が「型なし(untyped)」として扱われるという、長年Goコンパイラが採用してきた挙動と、仕様書の一部記述との間に乖離がありました。
コミットメッセージにもあるように、これは言語自体の変更ではなく、既存の振る舞いを正確に反映させるための「仕様の修正」です。Go言語の設計思想として、定数は可能な限り型なしとして扱われ、使用される文脈によって型が推論されるという柔軟性を持っています。このコミットは、その重要な特性を仕様書に明示的に記述することで、言語の定義をより明確にし、開発者の理解を深めることを目的としています。
前提知識の解説
Go言語における定数と型なし定数(Untyped Constants)
Go言語の定数(constants)は、プログラムの実行中に値が変わらない不変のエンティティです。Goの定数には、他の多くのプログラミング言語とは異なる、非常に重要な特性があります。それが「型なし定数(Untyped Constants)」の概念です。
-
型なし定数とは: 型なし定数は、特定のGoの型(例:
int
,float64
,string
,bool
)を持たない定数です。これらは「理想的な空間」に存在し、任意の精度を持つことができます。例えば、10
という整数定数は、それがint
型として使われるまでは、int8
、int16
、int32
、int64
のいずれにもなりうる型なしの整数定数として扱われます。 -
任意精度(Arbitrary Precision): 数値の型なし定数(整数、浮動小数点数、複素数)は、任意精度を維持します。これにより、コンパイル時に非常に高い精度で計算を実行でき、固定サイズの型で発生する可能性のあるオーバーフローや精度損失の懸念がありません。例えば、
const Huge = 1e1000
のような非常に大きな数値も、Goの標準的な数値型では表現できないにもかかわらず、有効な型なし定数として扱われます。 -
柔軟性と暗黙的な型付け: 型なし定数の主な利点は、その柔軟性です。これらは様々な文脈で使用でき、明示的な型変換の必要性を減らしながら、必要な型に暗黙的に適応します。型なし定数は、以下の状況で型を取得します。
- 変数への代入:
i := 0
のように、型が明示されていない変数に型なし定数が代入されると、変数の型は定数のデフォルト型になります。 - 式での使用: 型なし定数が型付きの値と式で相互作用する場合、定数は可能であれば他のオペランドの型に暗黙的に変換されます。
- 関数引数としての受け渡し: 関数パラメータが特定の型を持つ場合、型なし定数はその型に変換されます。
- 変数への代入:
-
デフォルト型(Default Types): 型なし定数が暗黙的に型に変換される場合(例:
i := 0
のような短い変数宣言)、その種類に基づいて「デフォルト型」が割り当てられます。- 真偽値定数 (
true
,false
):bool
- ルーン定数 (
'a'
):rune
(これはint32
のエイリアス) - 整数定数 (
10
):int
- 浮動小数点定数 (
3.14
):float64
- 複素数定数 (
1i
):complex128
- 文字列定数 (
"hello"
):string
- 真偽値定数 (
-
コンパイル時評価: Goのすべての定数(型なし定数を含む)は、コンパイル時に評価され解決されます。これらは実行時にメモリを占有せず、アドレスを取得することもできません。
このコミットは、特に真偽値定数と文字列定数が、比較演算の結果として、またはリテラルとして直接使用される場合に「型なし」として扱われるという、Go言語の重要な側面を仕様書に明記するものです。
技術的詳細
このコミットは、Go言語の仕様書 doc/go_spec.html
の「Constants」セクションにおける記述を修正し、型なし真偽値定数と型なし文字列定数に関する例を追加しています。
変更の核心は、比較演算の結果として得られる真偽値定数、およびリテラルとして定義される真偽値定数や文字列定数が、デフォルトで「型なし」として扱われることを明確にすることです。
具体的には、以下の点が修正されています。
-
比較演算の結果: 変更前:
A constant <a href="#Comparison_operators">comparison</a> always yields a constant of type <code>bool</code>.
変更後:A constant <a href="#Comparison_operators">comparison</a> always yields an untyped boolean constant.
これは、定数間の比較(例:1 > 0
や"foo" > "bar"
)の結果が、直接bool
型になるのではなく、「型なしの真偽値定数」になることを明記しています。これにより、その真偽値定数が後続の式や代入でより柔軟に型推論される余地が生まれます。例えば、const b = (1 > 0)
とした場合、b
は型なしの真偽値定数となり、var x bool = b
のようにbool
型変数に代入される際にbool
型に確定します。 -
型なし真偽値定数の例の追加:
const j = true
のような直接的な真偽値リテラルが、型なし真偽値定数として扱われることを示す例が追加されました。これは、true
やfalse
が単なるbool
型の値ではなく、他の数値定数と同様に、文脈に応じて型が決定される「型なし」の性質を持つことを強調しています。 -
型なし文字列定数の例の追加:
const l = "hi"
のような直接的な文字列リテラルが、型なし文字列定数として扱われることを示す例が追加されました。これも真偽値定数と同様に、文字列リテラルがデフォルトで型なしであり、使用される文脈でstring
型に確定することを示しています。 -
型変換による文字列定数の例の追加:
const m = string(k)
の例が追加されました。ここでk
は型なしの文字定数('w' + 1
の結果)であり、それをstring()
で型変換することで、m
がstring
型になることを示しています。これは、型なし定数がどのように型変換され、特定の型を持つ定数になるかを示す良い例です。
これらの変更は、Go言語の定数システム、特に型なし定数の振る舞いをより正確に、かつ包括的に記述するためのものです。これにより、Go言語の仕様が実際のコンパイラの挙動と完全に一致し、開発者が定数の型推論についてより深く理解できるようになります。
コアとなるコードの変更箇所
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -3408,7 +3408,7 @@ untyped complex constant yields an untyped complex constant.
<p>
A constant <a href="#Comparison_operators">comparison</a> always yields
-a constant of type <code>bool</code>. If the left operand of a constant
+an untyped boolean constant. If the left operand of a constant
<a href="#Operators">shift expression</a> is an untyped constant, the
result is an integer constant; otherwise it is a constant of the same
type as the left operand, which must be of integer type
@@ -3427,8 +3427,11 @@ const d = 1 << 3.0 // d == 8 (untyped integer constant)
const e = 1.0 << 3 // e == 8 (untyped integer constant)
const f = int32(1) << 33 // f == 0 (type int32)\n const g = float64(2) >> 1 // illegal (float64(2) is a typed floating-point constant)\n-const h = "foo" > "bar" // h == true (type bool)\n-const j = 'w' + 1 // j == 'x' (untyped character constant)\n+const h = "foo" > "bar" // h == true (untyped boolean constant)\n+const j = true // j == true (untyped boolean constant)\n+const k = 'w' + 1 // k == 'x' (untyped character constant)\n+const l = "hi" // l == "hi" (untyped string constant)\n+const m = string(k) // m == "x" (type string)\n const Σ = 1 - 0.707 // (untyped complex constant)\n const Δ = Σ + 2.0e-4 // (untyped complex constant)\n const Φ = iota*1i - 1/1i // (untyped complex constant)\n```
## コアとなるコードの解説
このコミットは、Go言語の仕様書 `doc/go_spec.html` の2つのセクションにわたる変更を含んでいます。
1. **3408行目付近の変更**:
`- a constant of type <code>bool</code>.`
`+ an untyped boolean constant.`
この変更は、定数間の比較演算(例: `x > y`)の結果が、直接`bool`型を持つ定数になるのではなく、「型なしの真偽値定数」になることを明確にしています。これは、Goの型なし定数の概念に沿った修正であり、比較結果がすぐに特定の型に固定されるのではなく、その後の文脈で型が決定される柔軟性を持つことを示しています。
2. **3427行目付近の例の追加と修正**:
* `-const h = "foo" > "bar" // h == true (type bool)`
`+const h = "foo" > "bar" // h == true (untyped boolean constant)`
`h`は文字列の比較結果ですが、これも型なしの真偽値定数として扱われることを明記しています。以前は`bool`型とされていましたが、これも型なし定数の原則に合わせるための修正です。
* `-const j = 'w' + 1 // j == 'x' (untyped character constant)`
`+const j = true // j == true (untyped boolean constant)`
`+const k = 'w' + 1 // k == 'x' (untyped character constant)`
元の`j`の例(文字定数)は`k`に移動し、新たに`j = true`という例が追加されました。これは、`true`という真偽値リテラルが、デフォルトで「型なしの真偽値定数」として扱われることを示しています。
* `+const l = "hi" // l == "hi" (untyped string constant)`
`l = "hi"`という例が追加されました。これは、文字列リテラル`"hi"`が、デフォルトで「型なしの文字列定数」として扱われることを示しています。これにより、文字列定数も数値定数や真偽値定数と同様に、使用される文脈によって型が決定される柔軟性を持つことが明確になります。
* `+const m = string(k) // m == "x" (type string)`
`m = string(k)`という例が追加されました。ここで`k`は型なしの文字定数(`'x'`)であり、それを`string()`で型変換することで、`m`が明示的に`string`型を持つ定数になることを示しています。これは、型なし定数がどのように型変換によって特定の型を持つ定数になるかを示す具体的な例です。
これらの変更は、Go言語の定数、特に型なし定数の振る舞いに関する仕様をより正確かつ詳細に記述し、言語の定義と実際のコンパイラの挙動との整合性を高めることを目的としています。
## 関連リンク
* Go CL 5477047: [https://golang.org/cl/5477047](https://golang.org/cl/5477047)
## 参考にした情報源リンク
* Go言語の仕様 - Constants: [https://go.dev/ref/spec#Constants](https://go.dev/ref/spec#Constants)
* Go言語の仕様 - Constant expressions: [https://go.dev/ref/spec#Constant_expressions](https://go.dev/ref/spec#Constant_expressions)
* Go言語の仕様 - Conversions: [https://go.dev/ref/spec#Conversions](https://go.dev/ref/spec#Conversions)
* Go by Example: Constants: [https://gobyexample.com/constants](https://gobyexample.com/constants)
* Untyped constants in Go: [https://boldlygo.tech/posts/2020/01/20/untyped-constants-in-go/](https://boldlygo.tech/posts/2020/01/20/untyped-constants-in-go/)
* Go: Untyped Constants: [https://yourbasic.org/golang/untyped-constants/](https://yourbasic.org/golang/untyped-constants/)
* Go: The Ultimate Guide to Constants: [https://www.ardanlabs.com/blog/2020/07/go-ultimate-guide-to-constants.html](https://www.ardanlabs.com/blog/2020/07/go-ultimate-guide-to-constants.html)
* Go: The Ultimate Guide to Constants (Part 2): [https://www.ardanlabs.com/blog/2020/07/go-ultimate-guide-to-constants-part-2.html](https://www.ardanlabs.com/blog/2020/07/go-ultimate-guide-to-constants-part-2.html)
* Go 101: Constants: [https://go101.org/article/constant.html](https://go101.org/article/constant.html)
* Stack Overflow: What is an untyped constant in Go?: [https://stackoverflow.com/questions/26830800/what-is-an-untyped-constant-in-go](https://stackoverflow.com/questions/26830800/what-is-an-untyped-constant-in-go)
* Reddit: What are untyped constants in Go?: [https://www.reddit.com/r/golang/comments/101010/what_are_untyped_constants_in_go/](https://www.reddit.com/r/golang/comments/101010/what_are_untyped_constants_in_go/)