1. 可排序、可比较和不可比较
- 可排序的数据类型有三种
- 整型Integer
- 浮点型Floating-point
- 字符串String
- 可比较的数据类型除了上述三种外,还有Boolean,Complex,Pointer,Channel,Interface和Array
不可比较的数据类型包括,Slice, Map, 和Function
2. 同一个struct的2个实例比较
包含不可比较的成员变量(map,slice,func等)
- ==操作符可以比较指针,不能直接比较实例;
- 不包含不可比较的成员变量
- ==操作符可以比较指针和实例;
- reflect.DeepEqual函数,指针和实例均可以比较(无论有没有包含不可比较的成员变量) ```go package main
import ( “fmt” “reflect” )
type T1 struct { Name string Age int Arr [2]bool ptr *int slice []int map1 map[string]string }
func main() { t1 := T1{ Name: “yxc”, Age: 1, Arr: [2]bool{true, false}, ptr: new(int), slice: []int{1, 2, 3}, map1: make(map[string]string, 0), }
t2 := T1{Name: "yxc",Age: 1,Arr: [2]bool{true, false},ptr: new(int),slice: []int{1, 2, 3},map1: make(map[string]string, 0),}// 报错 实例不能比较 Invalid operation: t1 == t2 (operator == not defined on T1)// fmt.Println(t1 == t2)// 指针可以比较fmt.Println(&t1 == &t2) // falsefmt.Println(reflect.DeepEqual(t1, t2)) // truet3 := &T1{Name: "yxc",Age: 1,Arr: [2]bool{true, false},ptr: new(int),slice: []int{1, 2, 3},map1: make(map[string]string, 0),}t4 := &T1{Name: "yxc",Age: 1,Arr: [2]bool{true, false},ptr: new(int),slice: []int{1, 2, 3},map1: make(map[string]string, 0),}fmt.Println(t3 == t4) // falsefmt.Println(reflect.DeepEqual(t3, t4)) // truefmt.Printf("%p, %p \n", t3, t4) // 0xc000046050, 0xc0000460a0fmt.Printf("%p, %p \n", &t3, &t4) // 0xc000006030, 0xc000006038// 前面加*,表示指针指向的值,即结构体实例,不能用==// Invalid operation: *t3 == *t4 (operator == not defined on T1)// fmt.Println(*t3 == *t4)t5 := t3fmt.Println(t3 == t5) // truefmt.Println(reflect.DeepEqual(t3, t5)) // truefmt.Printf("%p, %p \n", t3, t5) // 0xc000046050, 0xc000046050fmt.Printf("%p, %p \n", &t3, &t5) // 0xc000006030, 0xc000006040
}
<a name="XtxgV"></a>## 3. 两个不同的struct的实例能不能比较<a name="5qa2t"></a>### 3.1 两个struct可以相互转换,且不包含不可比较的成员变量,转换成相同类型后可以使用==操作符```gopackage mainimport ("fmt")type T2 struct {Name stringAge intArr [2]boolptr *int}type T3 struct {Name stringAge intArr [2]boolptr *int}func main() {var ss1 T2var ss2 T3// Cannot use 'ss2' (type T3) as type T2 in assignment//ss1 = ss2ss3 := T2(ss2)fmt.Println(ss3 == ss1) // true}
3.2 两个struct可以相互转换,但包含不可比较的成员变量
- 转化成相同类型后,不可以比较实例,可以比较指针;
- 一定要转化后再使用reflect.DeepEqual函数进行比较,否则总是返回false,失去了比较的意义; ```go package main
import ( “fmt” “reflect” )
type T2 struct { Name string Age int Arr [2]bool ptr *int map1 map[string]string }
type T3 struct { Name string Age int Arr [2]bool ptr *int map1 map[string]string }
func main() { var ss2 T2 var ss3 T3
// 不同类型的struct, 不可以直接用=赋值// Cannot use 'ss2' (type T2) as type T3 in assignment// ss2 = ss3// invalid operation: &ss2 == &ss3 (mismatched types *T2 and *T3)//fmt.Println(&ss2==&ss3)// invalid operation: ss2 == ss3 (mismatched types T2 and T3)//fmt.Println(ss2==ss3)fmt.Println(reflect.DeepEqual(ss3, ss2)) // falsefmt.Println(reflect.DeepEqual(&ss3, &ss2)) // falsess4 := T2(ss3)// Invalid operation: ss4==ss2 (operator == not defined on T2)//fmt.Println(ss4==ss2) //含有不可比较成员变量// 转化成相同类型后, 可以比较指针fmt.Println(&ss4==&ss2) // falsefmt.Println(reflect.DeepEqual(ss4, ss2)) // true
}
<a name="rC7Rl"></a>## 4. struct可以作为map的key么?- struct必须是可比较的,才能作为key,否则编译时报错```gopackage mainimport ("fmt")type T1 struct {Name stringAge intArr [2]boolptr *int//test func(i int) (err error)//slice []int//map1 map[string]string}type T2 struct {Name stringAge intArr [2]boolptr *int}func main() {n := make(map[T2]string, 0) // 无报错fmt.Print(n) // map[]// lnvalid map key type: the comparison operators == and != must be fully defined for key typem := make(map[T1]string, 0)fmt.Println(m)}
