基本类型

基本类型比较中变量类型必须相等(即使是int、int32这种也是不能比较的)

var a int
	b := 0
	fmt.Println(a==b) //true

	var c int32
	fmt.Println(a==c) // 无法比较int与int32将在编译时报错

	type INT int
	var d INT
	fmt.Println(a==d) // 无法比较int与INT(即使实际都是int),将在编译时报错

	type aliasInt = int
	var e aliasInt
	fmt.Println(a==e) // 类型别名,能够比较。 true

也即

  • 变量类型必须相等才能比较
  • 类型再定义也不能比较
  • int、int32等接近类型也不能比较
  • 类型别名能够比较

数组类型

对于数组而言,要求数组中所有数据必须是可比较的,且数组长度也要一致

var a [1]string
	var b [2]string
	fmt.Println(a == b) // 数组长度不一致,不能比较

	var c [1]int
	fmt.Println(a == c) // 数组元素类型不一致,也不能比较

	var d [1]string
	fmt.Println(a == d) //只有数组元素类型一致,且长度相等才能比较,但

	var e [1][]string
	var f [1][]string
	fmt.Println(e == f) // 若数组元素是不可比较类型,那么数组也不可以比较

总之对于能比较数组必须满足

  • 数组长度一致
  • 数组元素类型一致,且能比较

结构体类型

结构体类型只要结构成员是能比较的,那么结构体就能比较

type cmp struct {
		x int
		y string
	}
	a := cmp{
		x: 0,
		y: "",
	}

	b := cmp{
		x: 0,
		y: "",
	}
	fmt.Println(a == b) // 此时cmp结构所有成员都可以比较,因此结构之间也能比较

	type notCmp struct {
		x int
		y []string
	}
	c := notCmp{
		x: 0,
		y: nil,
	}
	d := notCmp{
		x: 0,
		y: nil,
	}
	fmt.Println(c == d) // 此时nocmp结构中含有不可比较的slice类型,那么结构便不能比较

指针类型

指针类型是基本类型指针以及slice、map。对于基本类型指针比较的是指针指向的是否为同一个地址

而slice、map则无法比较

var o int
	a := &o
	b := &o
	fmt.Println(a == b) // true

	var o1 int
	c := &o1
	fmt.Println(a == c) // false

	type simple struct {
		x int
		y string
	}

	d := &simple{}
	f := &simple{}
	g := d
	fmt.Println(d == f) // false
	fmt.Println(d == g) // true

interface{}类型

接口比较的是动态类型以及动态值,只有两者都相等时,比较才相等。

动态类型就是实际实现接口的结构类型,动态值就是实际实现接口的结构体

// 此时w声明为io.Writer接口,但并没有动态类型、动态值 var w io.Writer // 此时w有了动态类型*os.File,但由于f也只是个声明因此还没有动态值 var f *os.File w = f // 此时w才真的有了动态值 w = &os.File{}

type Person interface {
	getName() string
}

type student struct {
	Name string
}

type teacher struct {
	Name string
}

func (s student) getName() string {
	return s.Name
}

func (t teacher) getName() string {
	return t.Name
}

const name = "xiaoming"

func comparePerson(p1, p2 Person) bool {
	return p1 == p2
}

// student和teacher尽管继承同一个接口,拥有相同的属性、方法以及值,可是他们类型不同,所以仍然是不相等的
s1 := student{Name: name}
s2 := student{Name: name}
fmt.Println(comparePerson(s1, s2)) // true

t1 := teacher{Name: name}
fmt.Println(comparePerson(s1, t1)) // false

如果动态类型不能比较的话,那么也会不相等

type mapStudent map[string]string
type mapTeacher map[string]string

func (m mapStudent) getName() string {
	return m["key"]
}

func (m mapTeacher) getName() string {
	return m["key"]
}

ms1 := mapStudent{
  "key": name,
}
ms2 := mapTeacher{
  "key": name,
}
fmt.Println(comparePerson(ms1, ms2)) // false

函数类型

函数不可比较。

对于使用reflect.DeepEqual去硬比较,只要是两个不全是nil,返回结果都是不相等

硬要比较——slice、map

  • 对于byte slice类型,可以通过bytes.Equal进行比较
  • reflect.DeepEqual可以比较任意类型变量
  • 当然还可以引入第三方库进行比较

Ref

  1. https://www.jianshu.com/p/a982807819fa