Goでは、変数を==演算子で比較するか、それらをmapのキーとして使用することができるのは、その型がcomparableである場合です。比較可能なものには以下が含まれます:
int, float64, ...)string, rune)スライス、マップ、関数は比較不可能です!
これらの値を比較しようとすると、コンパイルエラーが発生します。例えば:
var a = []int{1,2,3} var b = []int{1,2,3} printf("%v", a==b) // compile error: slice can only be compared to nil
mapのキーとして値を使用するには、その値が比較可能でなければなりません。型が一致しない場合は、コンパイルエラーが発生します。
「もし構造体の一部のフィールドが比較不可能であっても、二つの構造体は比較可能と言えるか?」
多くの人が「はい」と答えますが、これは間違いです。構造体のフィールドのうち、少なくとも1つが比較不可能(例えば、スライスやマップである場合)であれば、その全体の構造体は比較不可能になります。
例:
type T struct { A int S []string } var t1, t2 T t1 == t2 // compile error: Slices are not comparable
エピソード
開発者は、計算結果をキャッシュするためにスライスをmapのキーとして使用しようとし、コンパイルエラーが発生しました。明示的なシリアライザーを使用した文字列に置き換えたところ、問題は解決しました。
エピソード
構造体に新しいフィールド(スライスタイプ)を追加したところ、突然プロジェクトがビルドできなくなりました。理由:その構造体が比較不可能になったため、これはネストされた構造体にまで影響が及ぶとは誰も予想していませんでした。
エピソード
スライスを含む構造体の集合(set)を作るためにmapを使用しようとしましたが、比較ルールを理解せずにエラーが発生しました。要素を比較しようとした際、ランタイムエラーが発生し、その理由はそのキーでコンパイルできなかったからでした。