ProgrammingGo 開発者

Goでは、どのデータ型が比較可能(comparable)と見なされ、比較不可能な型を比較しようとした場合はどうなりますか?これがmapやsetの使用にどのように影響しますか?

Hintsage AIアシスタントで面接を突破

回答

Goでは、変数を==演算子で比較するか、それらをmapのキーとして使用することができるのは、その型がcomparableである場合です。比較可能なものには以下が含まれます:

  • すべての数値型(int, float64, ...)
  • 文字(string, rune
  • ポインタ
  • チャネル
  • インターフェース(その値が比較可能である場合)
  • 配列(array)および構造体(struct)、すべてのフィールドが比較可能な場合

スライス、マップ、関数は比較不可能です!

これらの値を比較しようとすると、コンパイルエラーが発生します。例えば:

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を使用しようとしましたが、比較ルールを理解せずにエラーが発生しました。要素を比較しようとした際、ランタイムエラーが発生し、その理由はそのキーでコンパイルできなかったからでした。