Goには、未型指定(untyped)と型指定(typed)の2種類の定数があります。これは歴史的に、言語が型システムを柔軟かつ安全にすることを目指しており、コンパイラがコンパイル時にエラーを検出できるようにし、また、許可される場所でのみ型変換を行えるようにするためです。
問題は、プログラマーがこれら2つのカテゴリーを区別せず、関数やインターフェースの宣言における型の要件を考慮せず定数の挙動に依存した場合に発生します。これにより、型間の変換時にエラーが発生したり、予期しないコンパイルエラーが発生したり、関数呼び出し時に互換性の「飛び跳ね」が生じる可能性があります。
解決策は、以下の点を明確に理解することです:
const x int = 42)、この定数に対するさらなる操作は指定された型に制限されます。コード例:
const Pi = 3.14 // 未型指定 const Answer int64 = 42 // 型指定 func printInt(a int) { fmt.Println(a) } func main() { printInt(Pi) // エラー: Piはintではない(しかし明示的に変換できる) printInt(int(Pi)) // Ok printInt(Answer) // Ok、Answerはすでにint64であり、int64からintへの明示的な変換 }
主な特徴:
未型指定の定数をint型の変数に浮動小数点数として割り当てることはできますか?
いいえ。未型指定の定数は異なる型の式に挿入できますが、float定数をint型の変数に割り当てようとすると、コンパイルエラーが発生します。明示的な変換が必要です:
const Pi = 3.14 var x int = Pi // コンパイラはエラーを出力します var y int = int(Pi) // Ok
未型指定の定数は、最初の割り当て操作でその型に変わりますか?
いいえ、定数は特定の型が期待されるコンテキストに挿入されたり、明示的に宣言されたりするまで型を持ちません。それ以外の場合、未型のままです。
値が適合する場合、未型の大きな数値定数をより小さいサイズの変数の初期化に使用できますか?
はい、絶対値がターゲット型の範囲に収まる場合。そうでない場合、コンパイラはオーバーフローエラーを出力します。
例:
const Big = 1 << 62 var x int32 = Big // エラー: Bigはint32に収まらない var y int64 = Big // Ok
複雑な財務プロジェクトで、開発者たちは定数(割合、係数)を未型指定で宣言しました。あるとき、部分的な関数がfloat32を要求するようになりました。型の自動引き上げは、計算における精度の損失を引き起こし、すぐには認識されませんでした。
利点:
欠点:
システムの別の部分では、すべての定数が型を明示的に宣言しており、変換も明示的に行われています:
const Discount float64 = 0.05
利点:
欠点: