私が初めて Go を始めたとき、定数は単純で限定されたもの、つまり固定値だけで特別なことは何もないと思っていました。しかし、詳しく調べてみると、それらは非常に多用途であることがわかります。はい、それらは固定値ですが、Go は柔軟かつ効率的な方法でそれらを処理します。とてもクールです。それが何を意味するのか、いくつかの実際的な例で見てみましょう。
Go では、定数は実際に使用するまで型指定されないことがよくあります。これらにはデフォルトの種類がありますが、値が適合する限り、さまざまな型の変数に割り当てることができます。これにより、静的型付け言語では珍しい方法で適応性が高まります。
その様子は次のとおりです:
const x = 10 var i int = x var f float64 = x var b byte = x
シュレーディンガーのパラドックスと少し似ていますが、x は代入するまでは int、float64、またはバイトの場合もあります。この一時的な柔軟性により、x はコード内のさまざまな型をスムーズに処理できるようになります。キャストする必要がないため、すっきりとした状態が保たれます。
式の中で異なる型の定数を混合することもでき、Go は結果に最適な型を見つけ出します。
const a = 1.5 const b = 2 const result = a * b // result is float64
a は浮動小数点数であるため、Go は式全体を float64 にプロモートします。したがって、精度が失われることを心配する必要はありません。Go がそれを処理します。ただし注意してください。結果を int に代入しようとすると、エラーが発生します。 Go では、データを失う可能性のある暗黙的な変換は許可されません。
制限事項
この柔軟性はさらに効果的です。変数に定数を割り当てると、その変数の型が設定されます。
const y = 10 var z int = y // z is an int var k float64 = y // y can still be used as float64
しかし、これを試してみると:
const y = 10.5 var m int = y // Error: constant 10.5 truncated to integer
Go は明示的なキャストを行わないと浮動小数点定数を整数に自動的に変換しないため、エラーがスローされます。したがって、定数は柔軟ですが、互換性のない変数に合わせて型を変更することはありません。
型のデフォルトについて
型を指定せずに型なし定数を使用すると、デフォルトの型が想定されます。
型なし整数定数 のデフォルトは int です。
型なし浮動小数点定数 のデフォルトは float64 です。
型なしのルーン定数 のデフォルトは rune (int32) です。
型なし複合定数 のデフォルトは complex128 です。
型なしの文字列定数 のデフォルトは文字列です。
型なしのブール定数 のデフォルトは bool です。
これが簡単な表です:
Constant Kind | Can Adapt To |
---|---|
Untyped Integer | int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr, float32, float64, complex64, complex128 |
Untyped Float | float32, float64, complex64, complex128 |
Untyped Complex | complex64, complex128 |
Untyped Rune | rune, int32, any integer type that can hold the value |
Untyped String | string |
Untyped Boolean | bool |
Go はコンパイル時に定数を評価するだけでなく、定数式も最適化します。つまり、計算に定数を使用でき、Go はコンパイル中に結果を計算します。
const x = 10 var i int = x var f float64 = x var b byte = x
したがって、c は実行時に再計算されません。 Go はコンパイル時に 520 であることをすでに認識しています。これにより、特に速度が重要なコードのパフォーマンスが向上します。定数を使用すると、Go はプログラムを実行するたびに計算を行うのではなく、一度だけ計算を処理します。
Go には他の言語のようなプリプロセッサがありませんが、if ステートメントで定数を使用して、コンパイル時にコードを含めたり除外したりできます。
const a = 1.5 const b = 2 const result = a * b // result is float64
debug が false の場合、コンパイラーは if 条件が決して true にならないことを認識し、ブロック内のコードを除外する可能性があります。これにより、最終的なバイナリが小さくなる可能性があります。かなり便利ですよね?
Go の定数の強力な特徴の 1 つは、非常に大きな数値をサポートすることです。 Go の型なし数値定数は「無限」の精度を持ち、メモリとコンパイラによってのみ制限されます。
const y = 10 var z int = y // z is an int var k float64 = y // y can still be used as float64
bigNum は float64 や int のような組み込みの数値型よりもはるかに大きいですが、Go ではそれを定数として定義できます。コンパイル時にこれらの大きな数値を使用して計算を行うことができます:
const y = 10.5 var m int = y // Error: constant 10.5 truncated to integer
Go を使用している場合は、列挙型定数を作成するための iota を見たことがあるでしょう。自動的に増分値が割り当てられるので便利です。
iota を使用した定数宣言で式を使用して、関連する定数を作成することもできます。
const a = 100 const b = 5 const c = a * b + 20 // c is computed at compile time
このコードは、ビット シフトを使用してキロバイト、メガバイト、ギガバイト、テラバイトの定数を定義します。コンパイル時に計算されます。これは、一連の関連する定数を生成する優れた方法です。
この種のことにはiotaが本当に役立つと思います。 Go には組み込みの列挙型がないため、iota 識別子とカスタム型を使用して列挙型を効果的にシミュレートできます。
定数ではビット単位の演算やシフトを使用でき、組み込み型よりも大きな値になる場合もあります。
const debug = false func main() { if debug { fmt.Println("Debugging enabled") } // The above block might be removed by the compiler if debug is false }
ここではシフト量が大きいため、shiftValueは非常に大きな数値になります。この値は標準の整数型には大きすぎますが、割り当てを試行するまでは定数として有効です:
const bigNum = 1e1000 // This is a valid constant
これは、定数が変数に格納できない値を表すことができるため、非常に大きな数値を使用したコンパイル時の計算が可能であることを示しています。
Go の定数は柔軟ですが、できないこともいくつかあります。
定数はポインターによって参照できません
定数は実行時にメモリ アドレスを持ちません。したがって、定数のアドレスを取得したり、定数へのポインタを使用したりすることはできません。
const x = 10 var i int = x var f float64 = x var b byte = x
型付き nil ポインターを持つ定数
ポインター、スライス、マップ、チャネル、および関数型の変数に nil を割り当てることはできますが、型指定された nil ポインターを保持する定数を作成することはできません。
const a = 1.5 const b = 2 const result = a * b // result is float64
これにより、Go の定数の不変性とコンパイル時の性質が強化されます。
定数宣言での関数呼び出し
定数式では、len、cap、real、imag、complex などの特定の組み込み関数のみを使用できます。
const y = 10 var z int = y // z is an int var k float64 = y // y can still be used as float64
これらの組み込み関数が使用できるためです
複合型と定数
定数は、スライス、マップ、構造体のような複合型を直接表すことはできません。ただし、定数を使用して初期化できます。
const y = 10.5 var m int = y // Error: constant 10.5 truncated to integer
スライスを定数として宣言できないため、上記のコードは機能しません。ただし、変数スライス内で定数を使用できます:
const a = 100 const b = 5 const c = a * b + 20 // c is computed at compile time
スライスなどの型自体は定数ではないことを覚えておいてください。定数として宣言することはできません。ただし、内部の要素は定数にすることもできます。
必要な場合の明示的な変換
型の不一致または精度の損失の可能性により、型なし定数を直接割り当てることができない場合は、明示的な型変換を使用する必要があります。
const debug = false func main() { if debug { fmt.Println("Debugging enabled") } // The above block might be removed by the compiler if debug is false }
これがコンスタンスについてのより良い理解につながることを願っています。これらは単純な固定値だけではありません。コードをより表現力豊かかつ効率的にできる柔軟な機能でもあります。
私は Go の経験を共有することにまだ比較的慣れていないので、学んで改善することに熱心です。この投稿が有益であると思われた場合、またはこの投稿をより良くするための提案がある場合は、コメントに投稿してください。
「Go の UTF-8 サポート: 興味深い制限」(ログインは必要ありません) に関する私の初めての Reddit 投稿は、かなりの注目を集めました。
フィードバックをお待ちしております。
以上がGo の定数: 基本を超えての詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。