Golang中用==判断是否相等
本文介绍Go语言中 ==
在一些常见场景下的判断逻辑。
- 基础类型与指针
- struct
- interface
- chan
- array
- 不可用 == 比较的类型 func, slice, map
- reflect.DeepEqual
基础类型与指针
对于基础类型和指针,==
符号都是直接判断值是否相等。
因为指针的值实际上是内存地址,所以对于指针是否相等的判断和c语言一样都是看指针是否指向同一个内存地址
// 基础类型: int, string等, 都是值比较
var i1 = 2
var i2 = 2
var s1 = "hello"
var s2 = "hello"
fmt.Println(i1 == i2 && s1 == s2) // true
fmt.Println(&i1 == &i2 || &s1 == &s2) // false
// 指针类型: 地址比较
var p1 = &i1
var p2 = &i2
var p3 = &i1
fmt.Println(p1 == p2) // false
fmt.Println(p1 == p3) // true
struct
- 两个不同的类型的值之间不能比较
- 相同类型的值进行比较时,根据结构体中每一项是否相等来判断值是否相等(如果结构体中嵌套子结构体,也会用相同的逻辑去比较子结构体)
type B struct {
B1 int
B2 int
}
type A struct {
A1 int
Bc B
}
type C A
func main() {
a1 := A{A1: 1, Bc: B{B1: 1, B2: 1}}
a2 := A{A1: 1, Bc: B{B1: 1, B2: 1}}
a3 := A{A1: 1, Bc: B{B1: 1, B2: 2}}
fmt.Println(a1 == a2) // true
fmt.Println(a2 == a3) // false
fmt.Println(&a1 == &a2) // false
c := C{A1: 1, Bc: B{B1: 1, B2: 2}}
fmt.Println(c == a3) // cannot compare c == a3 (mismatched types C and A)
}
interface
判断interface是否相等时,会分别判断
- 值的类型是否相同
- 值是否相同
type A int
type B = A
type C int
type I interface{ m() }
func (a A) m() {}
func (c C) m() {}
func main() {
// A, B 是相同类型, C和A,B是不同类型
var a I = A(1)
var a1 I = A(2)
var b I = B(1)
var c I = C(1)
fmt.Println(a == b) // true
fmt.Println(a == a1) // false, 类型相同值不同
fmt.Println(b == c) // false, 类型不同
}
chan
两个channel如果要相等,有两种情况
- 都为nil
- chan结构体中的值完全相等
var ch1, ch2 chan int
fmt.Println(ch1 == ch2) // true
ch1 = make(chan int)
ch2 = make(chan int)
fmt.Println(ch1 == ch2) // false
ch2 = ch1 // 发生了chan结构体的复制, ch2和ch1结构体虽然位于不同的地址, 但结构体中的值(包括一些指针的值)是完全相等的
fmt.Println(ch1 == ch2) // true
fmt.Println(&ch1 == &ch2) // false, 它们指向不同的地址
array
要求
- 数组长度相同
- 数组中每一项的值相同
type T struct {
name string
age int
_ float64
}
func main() {
x := [...]float64{1.1, 2, 3.14}
fmt.Println(x == [...]float64{1.1, 2, 3.14}) // true
y := [1]T{{"foo", 1, 0}}
fmt.Println(y == [1]T{{"foo", 1, 1}}) // true
}
不可用 ==
比较的类型 func
, slice
, map
它们即使类型相同也不能用==
相互比较,它们只能和nil用 ==
比较
func main() {
f := func(int) int { return 1 }
// g := func(int) int { return 2 }
// f == g // cannot compare f == g (operator == not defined for func(int) int)
m1 := make(map[int]int)
// m2 := make(map[int]int)
// m1 == m2 // cannot compare m1 == m2 (operator == not defined for map[int]int)
var slice1 []int
// var slice2 []int
// slice1 == slice2 // cannot compare slice1 == slice2 (operator == not defined for []int)
fmt.Println(f == nil) // false
fmt.Println(m1 == nil) // false
fmt.Println(slice1 == nil) // true
}
reflect.DeepEqual
对于map和slice,可以用reflect.DeepEqual来比较是否相等
m1 := make(map[int]int)
m2 := make(map[int]int)
fmt.Println(reflect.DeepEqual(m1, m2)) // true
var slice1 []int = []int{1, 2, 3}
var slice2 []int = []int{1, 2, 3}
fmt.Println(reflect.DeepEqual(slice1, slice2)) // true
但对于func类型,需要用reflect.TypeOf来判断函数是否相同
f := func(int) int { return 1 }
g := func(int) int { return 1 }
fmt.Println(reflect.DeepEqual(f, g)) // false
fmt.Println(reflect.TypeOf(f) == reflect.TypeOf(g)) // true
参考: https://medium.com/golangspec/equality-in-golang-ff44da79b7f1