Goでは、明示的な初期化子なしに宣言された変数は、自動的にいわゆる_ゼロ値_(zero values)を取得します。これは異なるタイプによって異なります:
int — 0bool — falsestring — ""これは便利ですが(メモリ内のゴミがないため)、危険な場合があります。たとえば、スライスやマップのような一部のタイプでは、nil値を扱うことがパニックやバグにつながる可能性があります。
例:
var m map[string]int m["key"] = 1 // panic: nilマップへのエントリの割り当て var s []int fmt.Println(s, s == nil) // [] true (要素を追加できますが、インデックスでアクセスすることはできません)
nilスライスのnil値とnilマップ/チャネルのnil値の違いは何ですか?また、それはどのようなバグを引き起こしますか?
正しい答え:nil値のスライスは関数に渡したり、appendやrangeで使用することができます。これは安全ですが、nilマップでの作業は書き込みを試みるとパニックを引き起こします(ただし、読み取りは許可されておりゼロ値を返します)。
例:
var m map[string]int fmt.Println(m["no_key"]) // 0 — 安全 m["key"] = 1 // panic! var s []int s = append(s, 42) // ok
物語
説明: 大規模なプロジェクトで、データ集約に未初期化のマップを使用しました。最初の書き込み時にアプリケーションが安定してpanicで落ちました。問題は、新しい統計を導入したときにプロダクションで発見されました。
物語
説明: サービスは未初期化のスライスをシリアライズし、API応答としてJSONで送信しました。クライアントは
[]の代わりにnullを受け取り、両方のバリエーションを処理するためにフロントエンドのスキーマを変更する必要がありました。
物語
説明: キャッシュモジュールでnilマップと空のマップを不適切に比較し、その結果、要素が存在するかどうかを正しく判断できませんでした。これによりデータベースへの余分な呼び出しが発生し、パフォーマンスが低下しました。