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) // false
fmt.Println(reflect.DeepEqual(t1, t2)) // true
t3 := &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) // false
fmt.Println(reflect.DeepEqual(t3, t4)) // true
fmt.Printf("%p, %p \n", t3, t4) // 0xc000046050, 0xc0000460a0
fmt.Printf("%p, %p \n", &t3, &t4) // 0xc000006030, 0xc000006038
// 前面加*,表示指针指向的值,即结构体实例,不能用==
// Invalid operation: *t3 == *t4 (operator == not defined on T1)
// fmt.Println(*t3 == *t4)
t5 := t3
fmt.Println(t3 == t5) // true
fmt.Println(reflect.DeepEqual(t3, t5)) // true
fmt.Printf("%p, %p \n", t3, t5) // 0xc000046050, 0xc000046050
fmt.Printf("%p, %p \n", &t3, &t5) // 0xc000006030, 0xc000006040
}
<a name="XtxgV"></a>
## 3. 两个不同的struct的实例能不能比较
<a name="5qa2t"></a>
### 3.1 两个struct可以相互转换,且不包含不可比较的成员变量,转换成相同类型后可以使用==操作符
```go
package main
import (
"fmt"
)
type T2 struct {
Name string
Age int
Arr [2]bool
ptr *int
}
type T3 struct {
Name string
Age int
Arr [2]bool
ptr *int
}
func main() {
var ss1 T2
var ss2 T3
// Cannot use 'ss2' (type T3) as type T2 in assignment
//ss1 = ss2
ss3 := 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)) // false
fmt.Println(reflect.DeepEqual(&ss3, &ss2)) // false
ss4 := T2(ss3)
// Invalid operation: ss4==ss2 (operator == not defined on T2)
//fmt.Println(ss4==ss2) //含有不可比较成员变量
// 转化成相同类型后, 可以比较指针
fmt.Println(&ss4==&ss2) // false
fmt.Println(reflect.DeepEqual(ss4, ss2)) // true
}
<a name="rC7Rl"></a>
## 4. struct可以作为map的key么?
- struct必须是可比较的,才能作为key,否则编译时报错
```go
package main
import (
"fmt"
)
type T1 struct {
Name string
Age int
Arr [2]bool
ptr *int
//test func(i int) (err error)
//slice []int
//map1 map[string]string
}
type T2 struct {
Name string
Age int
Arr [2]bool
ptr *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 type
m := make(map[T1]string, 0)
fmt.Println(m)
}