本文介紹Go語言中 ==
在一些常見場景下的判斷邏輯。
基礎類型與指針
對於基礎類型和指針,==
符號都是直接判斷值是否相等。
因為指針的值實際上是內存地址,所以對於指針是否相等的判斷和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