golang 等值比较是不是直接比较地址呢?

比如两个对象a==b直接比较的是地址,字符串和int float比较的直接是值吗?error类型呢

阅读 5.1k
2 个回答

Go 语言的数据类型都是值类型,定义的是什么类型,就是比较的是什么。怎么理解呢?也就是你定义的是整型变量,就是按整形变量的值比较,定义布尔型就按 true 和 false 比较,指针类型就按指针地址比较。

不同于其他语言,Go 中可比较的数据类型是语言内置的,没有操作符重载的能力。可比较的类型有布尔、整型、浮点型、字符串、数组、接口、结构体、channel 等。

你说的 error 其实是接口类型,也就是 interface 类型,它不仅仅会比较接口中的 Value,所有如果 error 的结构体类型不同,值相同也是不相等的,还会比较 Type。大概就是这么个意思。

一个简单测试案例:

package main

import "fmt"

type OneError struct{}

func (o OneError) Error() string {
    return "error"
}

type TwoError struct{}

func (o TwoError) Error() string {
    return "err"
}

func main() {
    var one error = OneError{}
    var two error = TwoError{}

    fmt.Println(one == two)  // false

    var anotherOne error = OneError{}
    fmt.Println(anotherOne == one)  // true
}

golang中数据类型分为4大类:
1.基础类型:各种int,bool,string等,这种类型的比较没什么好说的,直接比较值。
2.复合类型(又叫做聚合类型):数组和结构体,这种类型的比较是逐字段比较的。
3.引用类型:slice,map,channel,还有指针,除了slice,剩下的都是通过地址来比较的。slice后面说。
4.接口类型,interface。接口类型的值(称为接口值)其实由两部分组成,具体类型(即该接口存储的值的类型)和该类型的一个值。按照《go程序设计语言》的称谓,分别称为动态类型和动态值。接口类型的比较涉及这两部分的比较,只有当动态类型完全相同且动态值相等(动态值使用==比较),两个接口值才是相等的。

需要注意的是,由于下面两点原因,golang干脆规定,切片类型不可比较
1.切片是间接的类型,可以引用自身,有循环引用的问题(如切片[]interface{}中元素可以是任何类型,当然包括自己),实现深度比较难度较大,得不偿失。
2.但是如果直接比较引用的话,与数组的行为不一致,容易造成混淆。

由于不可比较类型的存在,导致比较操作有一些出乎意料的地方:
1.如果复合类型中有不可比较的类型,那么复合类型就不可比较。例如数组中的元素是切片类型,结构体中含有切片类型的字段等。
2.如果接口值的动态值不可比较,那么直接比较会panic,如:

var a interface{} = []int{1, 2, 3}
var b interface{} = []int{4, 5, 6}
fmt.Println(a == b)
// panic: runtime error: comparing uncomparable type []int

建议翻阅《go程序设计语言》一书的第四章《复合数据类型》和第七章《接口》,有比较详细的说明。

1 篇内容引用
推荐问题
宣传栏