Golang Go语言中引用类型进行比较的问题请教
Golang Go语言中引用类型进行比较的问题请教
请教一个 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 没有呢???
更多关于Golang Go语言中引用类型进行比较的问题请教的实战教程也可以访问 https://www.itying.com/category-94-b0.html
C++的思维看,大概是 channel 实现了对==的重载,而 slice 和 map 没实现
更多关于Golang Go语言中引用类型进行比较的问题请教的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
go 的 = 操作,就是简单的内存比较
slice 的内存不连续,slice header 和 data 分开放的,所以不能比较
map 的内存不连续,bucket 是分开放的,所以不能比较
chan 的内存是连续的,就一个对象,所以可以比较
在 Go 中,slice/map/function 值不能比较的原因是程序员这些值的比较规则有着不同的看法,所以干脆禁止这些值的比较,以防止引起困惑。
比如,对于 map,有些人认为两个引用着同一个底层哈希表的 maps 相等,有的人则认为这样两者中存储的键值对完全一致,则两者相同。对于这第二种理解,很难处理含有 NaN 键值的 maps。
对于 slice,有些人认为两者的长度和底层元素指针相同则相等,有些人认为两者的长度 /容量和底层元素指针必须都相等,有些人认为底层元素指针不必相等,只要它们对应的元素一一相等即可。
因为 Go 中的函数均可以看作闭包,这导致了很多人对函数相等有不同的理解。有些人认为两个函数的底层指针相等即相等,有些人认为两者内部的代码实现相等即相等,有些人认为两个函数在相同的输入下必须总是产生相同的输出才相等。
因为这些看法上的分歧,Go 干脆禁止 slice/map/function 值的比较。
非常感谢你们的回答,获益匪浅,谢谢。
在Go语言中,引用类型的比较是一个常见但需要注意的问题。首先,要明确的是,Go语言的比较操作符(== 和 !=)只支持相同类型的比较,并且对于引用类型(如指针、切片、映射、通道、接口等),它们比较的是底层指针的值,而不是引用数据的内容。
对于指针类型,如果你比较两个指针是否指向相同的内存地址,那么可以直接使用==或!=。但如果想比较指针指向的内容,你需要解引用指针并逐字段或元素进行比较。
对于切片、映射和通道,因为它们的底层实现包含指针和长度/容量信息,直接比较切片、映射和通道变量本身通常没有意义,也不会如你所期望的那样工作。如果需要比较它们的内容,你需要实现自定义的比较逻辑。
接口类型的比较稍微复杂一些,因为接口内部包含一个指向具体值的指针和一个类型信息。当你比较两个接口值时,如果它们都是nil或者都指向相同类型和值的底层具体变量,那么比较结果为真。
总之,在Go语言中处理引用类型的比较时,要特别注意你正在比较的是什么。大多数情况下,你需要通过显式地比较底层数据(例如,遍历切片或映射的元素)来实现有意义的比较逻辑。如果你发现自己频繁需要这样做,可能需要考虑使用更合适的数据结构或设计模式来简化代码和提高效率。