Go言語では、静的な厳密型付けが実装されています。つまり、変数の型はコンパイル時に知られており、コンパイラは互換性のない型に対する操作を許可しません。
型変換には2つの種類があります:
明示的な型変換の例:
var i int = 42 var f float64 = float64(i)
タイプアサーションの例:
var i interface{} = "hello" s, ok := i.(string) if ok { fmt.Println("String value:", s) } else { fmt.Println("iはstringではありません") }
型変換は、互換性のある基本型同士(int → float64, rune → int32, ただしstring → intは不可能)のみで可能です。
interface{}はnil値を保持できるか?また、インターフェース型の変数が本当にnilであるかを正しく確認する方法は?
一般的な罠は、nil値を保持するインターフェースをnilと直接比較することです:
var err error = nil var i interface{} = err fmt.Println(i == nil) // trueを期待しますが、falseになります!
正しい方法:
インターフェース自体がnilであり、内包されている値もnilであることを確認します:
if i == nil || reflect.ValueOf(i).IsNil() { fmt.Println("iは実際にnilです") }
物語
バックエンドプロジェクトで、開発者はさまざまなエラーをinterface{}を通じて処理しようとし、それらをnilと比較しました。その結果、エラーが正しく検出されず、隠れたバグやクライアントへのエラー返却の不正なロジックが発生しました。
物語
float64とintの間の明示的なキャストなしの移行は、サイレントデータロスを引き起こしました:値が丸められたり、不正確に移行されたりしました。Goのコンパイラは、そのような操作には明示的な変換を要求します。
物語
map[string]interface{}(例えば、JSONから)のインターフェース値のデシリアライズ時に、予期しないタイプのnumbers(float64)が発生し、追加のチェックなしでタイプアサーションを使用するとパニックが発生し、サービスがランタイムエラーでクラッシュしました。