You need to loop over each of the elements in the slice and test. Equality for slices is not defined. However, there is a bytes.Equal function if you are comparing values of type []byte.
func testEq(a, b []Type) bool {
// If one is nil, the other must also be nil.
if (a == nil) != (b == nil) {
return false;
}
if len(a) != len(b) {
return false
}
for i := range a {
if a[i] != b[i] {
return false
}
}
return true }
在 Golang 中 slice、map、channel 都是引用类型,因为是引用类型,所以 slice 和 map 不能使用 == 进行比较这里还能理解,可是为什么 channel 可以用 == 进行比较呢??
如下代码
package main
import “fmt”
import _ “reflect”
func main() {
ch1 := make(chan int)
ch2 := make(chan int)
fmt.Println(ch1 == ch2)
s1 := []int{1,2}
s2 := []int{2,1}
fmt.Println(s1 == s2)
m1 := make(map[int]int)
m2 := make(map[int]int)
fmt.Println(m1 == m2) } 输出结果为
./gotest.go:13:20: invalid operation: s1 == s2 (slice can only be compared to nil)
./gotest.go:17:20: invalid operation: m1 == m2 (map can only be compared to nil)
代码中,slice 和 map 使用 == 进行比较都报错了,为什么 channel 没有呢???
C++的思维看,大概是 channel 实现了对==的重载,而 slice 和 map 没实现
go 的 = 操作,就是简单的内存比较
slice 的内存不连续,slice header 和 data 分开放的,所以不能比较
map 的内存不连续,bucket 是分开放的,所以不能比较
chan 的内存是连续的,就一个对象,所以可以比较
在 Go 中,slice/map/function 值不能比较的原因是程序员这些值的比较规则有着不同的看法,所以干脆禁止这些值的比较,以防止引起困惑。
比如,对于 map,有些人认为两个引用着同一个底层哈希表的 maps 相等,有的人则认为这样两者中存储的键值对完全一致,则两者相同。对于这第二种理解,很难处理含有 NaN 键值的 maps。
对于 slice,有些人认为两者的长度和底层元素指针相同则相等,有些人认为两者的长度 /容量和底层元素指针必须都相等,有些人认为底层元素指针不必相等,只要它们对应的元素一一相等即可。
因为 Go 中的函数均可以看作闭包,这导致了很多人对函数相等有不同的理解。有些人认为两个函数的底层指针相等即相等,有些人认为两者内部的代码实现相等即相等,有些人认为两个函数在相同的输入下必须总是产生相同的输出才相等。
因为这些看法上的分歧,Go 干脆禁止 slice/map/function 值的比较。
https://gfw.go101.org/article/value-conversions-assignments-and-comparisons.html#comparison-implementation
nil 标识符是不能比较的
package main
import “fmt”
func main() {
fmt.Println(nil == nil)
}
.\nil.go:6:18: invalid operation: nil == nil (operator == not defined on nil)
func main() {
b := []int{}
var c []int
fmt.Println(nil == nil)
fmt.Println(b == nil, b, c == nil, c)
fmt.Println(b == c)
}
./compile8.go:8:18: invalid operation: nil == nil (operator == not defined on nil)
false [] true [] //nil表示是非初始化对象,内存地址都是0, 初始化后是empty对象这个时候不是nil
./compile8.go:10:16: invalid operation: b == c (slice can only be compared to nil)
nil 不是关键字或保留字
nil 并不是Go语言的关键字或者保留字,也就是说我们可以定义一个名称为 nil 的变量,比如下面这样:
var nil = errors.New(“my god”)
虽然上面的声明语句可以通过编译,但是并不提倡这么做。
不同类型 nil 的指针是一样的
复制代码
package main
import “fmt”
func main() {
//fmt.Println(nil == nil)
var arr []int
var num *int
var string *string
fmt.Printf("%p\n", arr)
fmt.Printf("%p\n", num)
fmt.Printf("%p\n", string)
}
复制代码
0x0
0x0
0x0
通过运行结果可以看出 arr 、num、 string 的指针都是 0x0。
不同类型的 nil 是不能比较的
复制代码
package main
import “fmt”
func main() {
var arr []int
var num *int
var string *string
fmt.Printf("%p\n", arr)
fmt.Printf("%p\n", num)
fmt.Println(arr == num)
}
复制代码
.\nil.go:14:18: invalid operation: arr == num (mismatched types []int and *int)
两个相同类型的 nil 值也可能无法比较
在Go语言中 map、slice 和 function 类型的 nil 值不能比较,比较两个无法比较类型的值是非法的,下面的语句无法编译。
var s1 []int
var s2 []int
fmt.Printf(“\n”, s1 == s2)
.\nil.go:16:22: invalid operation: s1 == s2 (slice can only be compared to nil)
nil 是 map、slice、pointer、channel、func、interface 的零值
复制代码
package main
import “fmt”
func main() {
var m map[int]string
var ptr *int32
var c chan int32
var slice []int32
var f func()
var i interface{}
fmt.Printf("%#v \n", m)
fmt.Printf("%#v \n", ptr)
fmt.Printf("%#v \n", c)
fmt.Printf("%#v \n", slice)
fmt.Printf("%#v \n", f)
fmt.Printf("%#v \n", i) } 复制代码 复制代码 map[int]string(nil) (*int32)(nil) (chan int32)(nil) []int32(nil) (func())(nil)