请教一个 Golang 中引用类型进行比较的问题。

2019-04-25 20:27:23 +08:00
 peanuts7660

请教一个 Golang 中进行比较的问题。

在 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)
}

输出结果为

# command-line-arguments
./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 没有呢???

2815 次点击
所在节点    Go 编程语言
5 条回复
LANB0
2019-04-25 20:37:22 +08:00
C++的思维看,大概是 channel 实现了对==的重载,而 slice 和 map 没实现
reus
2019-04-25 21:13:06 +08:00
go 的 = 操作,就是简单的内存比较

slice 的内存不连续,slice header 和 data 分开放的,所以不能比较

map 的内存不连续,bucket 是分开放的,所以不能比较

chan 的内存是连续的,就一个对象,所以可以比较
liulaomo
2019-04-26 10:23:05 +08:00
在 Go 中,slice/map/function 值不能比较的原因是程序员这些值的比较规则有着不同的看法,所以干脆禁止这些值的比较,以防止引起困惑。

比如,对于 map,有些人认为两个引用着同一个底层哈希表的 maps 相等,有的人则认为这样两者中存储的键值对完全一致,则两者相同。对于这第二种理解,很难处理含有 NaN 键值的 maps。

对于 slice,有些人认为两者的长度和底层元素指针相同则相等,有些人认为两者的长度 /容量和底层元素指针必须都相等,有些人认为底层元素指针不必相等,只要它们对应的元素一一相等即可。

因为 Go 中的函数均可以看作闭包,这导致了很多人对函数相等有不同的理解。有些人认为两个函数的底层指针相等即相等,有些人认为两者内部的代码实现相等即相等,有些人认为两个函数在相同的输入下必须总是产生相同的输出才相等。

因为这些看法上的分歧,Go 干脆禁止 slice/map/function 值的比较。
liulaomo
2019-04-26 10:26:38 +08:00
peanuts7660
2019-04-26 11:17:43 +08:00
@LANB0 @liulaomo @reus 非常感谢你们的回答,获益匪浅,谢谢。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/558737

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX