Comparable

比较运算符比较两个操作数并产生一个无类型的布尔值。

==    equal
!=    not equal
<     less
<=    less or equal
>     greater
>=    greater or equal

比较运算前提:在任何比较中,第一个操作数必须可分配给第二个操作数的类型,反之亦然。如一个 int32 的整数无法于 int64 的直接进行比较运算。

var a int32 = 1
var b int64 = 1
fmt.Println(a > b)  // invalid operation: a > b (mismatched types int32 and int64)

相等运算符==和!=应用于可比较的操作数。排序运算符<、<=、>和>=应用于排序的操作数。

可比较类型

  • 布尔型 具有可比性。如果两个布尔值都为真或都为假,则它们是相等的。
  • 整数值按照通常的方式是可比较的和有序的。但要注意区分 int8 int16 int32 int64 它们不能直接进行比较运算。
  • 浮点值是可比较的和有序的。
  • 复数值是可比较的。如果实数(u) ==实数(v)和imag(u) == imag(v)两个复数值u和v相等。
  • 字符串具有可比性,并按词法字节顺序排列。
  • 指针是可比较的。两个指针值是相等的,如果它们指向同一个变量,或者两个指针值都为nil。指向不同大小为零的变量的指针可能相等,也可能不相等。
  • chan 是可比较的。两个通道的值是相等的,如果它们是由同一个调用创建的,或者如果两个通道的值都为nil。
  • interface{}是可比较的。如果两个接口值具有相同的动态类型和相等的动态值,或者两个接口值都为nil,则两个接口值是相等的。 当类型x的值是可比较的,并且x执行t时,非接口类型x的值x和接口类型t的值t是可比较的,如果t的动态类型和x相同,t的动态值等于x,则两者相等。
  • 如果结构值的所有字段都是可比较的,则结构值是可比较的。如果两个结构值对应的非空白字段相等,则两个结构值相等。
  • 如果数组元素类型的值是可比较的,则数组值是可比较的。如果两个数组的对应元素相等,则两个数组值相等。

不可比较类型

slice 是不可比较类型,但是数组是可比较的(当数组中的元素是可比较时)。

map 是不可比较类型。

function 是不可比较类型。

比较具有相同动态类型的两个接口值,如果该类型的值不可比较,则会导致运行时恐慌。这种行为不仅适用于直接的接口值比较,也适用于将接口值数组或结构与接口值字段进行比较。

切片、映射和函数值是不可比较的。但是,作为一种特殊情况,片、映射或函数值可以与预先声明的标识符nil进行比较。指针、通道和接口值与nil的比较也是允许的,符合上面的一般规则。

动手

通过反射查看是否可比较

func comparableType() {
   var b bool = true
   var i int = 1
   var f float64 = 1.0
   var s string = ""
   var ptr *int = &i
   var ch = make(chan int)
   var it error = errors.New("error interface")
   var struc = struct{x int}{x: 1}
   var array = [3]int{1,2,3}
   var slice = make([]int, 0, 3)  // 不可比较
   var m = map[string]int{
      "id":1,
   }
   
   fmt.Println("bool: ", reflect.TypeOf(b).Comparable())
   fmt.Println("int: ", reflect.TypeOf(i).Comparable())
   fmt.Println("float: ", reflect.TypeOf(f).Comparable())
   fmt.Println("string: ", reflect.TypeOf(s).Comparable())
   fmt.Println("pointer: ", reflect.TypeOf(ptr).Comparable())
   fmt.Println("chan: ", reflect.TypeOf(ch).Comparable())
   fmt.Println("interface: ", reflect.TypeOf(it).Comparable())
   fmt.Println("struct: ", reflect.TypeOf(struc).Comparable())
   fmt.Println("array: ", reflect.TypeOf(array).Comparable())
   fmt.Println("slice: ", reflect.TypeOf(slice).Comparable())
   fmt.Println("map: ", reflect.TypeOf(m).Comparable())
}

运行结果

Is comparable:

bool: true int: true float: true string: true pointer: true chan: true interface: true struct: true array: true slice: false map: false

扩展阅读

https://golang.org/ref/spec#Comparison_operators

更新时间: