编程Go开发者

在Go中,哪些数据类型被认为是可比较的(comparable),以及在尝试比较不可比较类型时会发生什么?这如何影响map和set的使用?

用 Hintsage AI 助手通过面试

回答

在Go中,只有当变量的类型为comparable时,它们才能使用==运算符进行比较或用作map的键。可比较的类型包括:

  • 所有数字类型(intfloat64,...)
  • 字符串(stringrune
  • 指针
  • 通道
  • 接口(如果它们的值是可比较的)
  • 数组(array)和结构体(struct),如果它们的所有字段都是可比较的

切片、map、函数 — 不可比较!

尝试比较这些值会导致编译错误。例如:

var a = []int{1,2,3} var b = []int{1,2,3} printf("%v", a==b) // 编译错误:切片只能与nil比较

要将值用作map的键,它必须是可比较的。如果类型不符合,即会出现编译错误。

有误导性的问题

“如果只有部分字段不可比较,两个结构体可以被认为是可比较的吗?”

许多人回答“可以”,但这是不正确的。如果结构体的至少一个字段不可比较(例如,这是一个切片或map),整个结构体就变得不可比较。

例子:

type T struct { A int S []string } var t1, t2 T t1 == t2 // 编译错误:切片不可比较

由于对主题细微差别的不理解而造成的实际错误示例


故事

开发人员尝试使用切片作为map的键来缓存计算结果,导致编译错误。将其替换为带有显式序列化器的字符串 — 问题解决了。


故事

在向用作字典键的结构中添加新字段(类型为切片)后,项目突然无法编译。原因:现在结构变得不可比较,但没有人预料到这会影响嵌套结构。


故事

为了基于包含切片的结构创建集合(set),尝试使用map。在没有了解比较规则的情况下,尝试比较元素时遇到许多运行时错误,但原因在于无法用这样的键进行编译。