go 类型直接比较
结构体能否比较?数组能否比较?slice、map、channel能否比较?接口能否比较?函数能否比较?
结构体比较
能用"==“直接比较的我们才称其为能比较。
类型不同的都不能直接比较,类型别名可以。不同类型可以先强转再比较。 相同类型时,字段都是可比较类型才能直接比较。
type T2 struct {
Name string
Age int
}
type T22 T2
type T222 = T2
type T3 struct {
Name string
Age int
}
func main() {
t2 := T2{}
t22 := T22{}
t222 := T222{}
t3 := T3{}
fmt.Println(t2==t222) // =起别名能比较
fmt.Println(t2==t22) // 类型定义不能比较
fmt.Println(t2==t3) // 不同类型,哪怕字段完全相同不能比较
t33:=T3(t2)
fmt.Println(t3==t33) // 不同类型,可以先强转再比较
}
结构体字段顺序、类型、字段名完全相同才可以强转。
数组比较
数组可以直接比较。前提是数组长度和类型相同,而且数组里面的元素是可以直接比较的。
func main() {
arr1:=[2]int{}
arr2:=[2]int{}
fmt.Println(arr1==arr2) // 可以比较
arr11:=[2][]int{}
arr22:=[2][]int{}
fmt.Println(arr11==arr22) // invalid operation: arr11 == arr22 ([2][]int cannot be compared)
}
channel比较
channel可以直接比较,比较的是channel的地址
func main() {
c1:=make(chan int)
c2:=make(chan int)
c11:=make(chan []int)
c22:=make(chan []int)
fmt.Println(c1==c2) // false
fmt.Println(c11==c22) // false
}
slice、map比较
slice不能直接比较。slice之间之所以不能进行比较,是因为slice的元素是间接引用的。slice引用的底层数组的元素随时可能会被修改,即slice在不同的时间可能包含不同的值,所以无法进行比较。 map不能直接比较。
接口比较
接口类型的变量,包含该接口变量存储的值和值的类型两部分组成,分别称为接口的动态类型和动态值。只有动态类型和动态值都相同时,两个接口变量才相同
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
}
func compare(s, t Person) bool {
return s == t
}
func main() {
s1 := Student{"minping"}
s2 := Student{"minping"}
t := Teacher{"minping"}
fmt.Println(compare(s1, s2)) //true
fmt.Println(compare(s1, t)) //false,类型不同
}
接口的动态类型必须要是可比较的,如果不能比较(比如slice,map),则运行时会报panic。因为编译器在编译时无法获取接口的动态类型,所以编译能通过,但是运行时直接panic
函数比较
golang的func作为一等公民,也是一种类型,而且不可比较
type GetName func ()
type GetName2 func ()
func main() {
var f1 GetName
var f2 GetName
fmt.Println(f1==f2) // invalid operation: f1 == f2 (func can only be compared to nil)
}
总结
1.结构体等复合类型,只有每个元素(成员)可比较且相同类型时能比较。类型和值都相等时,两个复合元素才相等 2.slice,map不可比较,但是可以用reflect或者cmp包来比较 3.func作为golnag的一等公民,也是一个类型,也不能比较。 4.channel引用类型的比较是看指向的是不是同一个变量 5.类型再定义(type A string)不可比较,是两种不同的类型 6.类型别名(type A = string)可比较,是同一种类型。 7.reflect.DeepEqual函数可以用来比较两个任意类型的变量