在 Go 中,数据类型按照比较性可被分为两类:
- 可比较类型,可比较类型可以使用运算符==和!=
- 不可比较类型,如果使用==或!=进行运算,那么会产生 panic
Boolean、Integer、Floating-point、Complex、String
Boolean(布尔值)、Integer(整型)、Floating-point(浮点数)、Complex(复数)、String(字符)这些类型可直接比较。
指针
指针可以比较。
数组
在长度和类型相同的数组是可以比较,长度不同或者类型不同的数组不能比较
slice
slice是不可以比较的,但是可以与 nil
进行比较。
map
map是不可以比较的,但是可以与 nil
进行比较。
function
function 是不可以比较的,但是可以与 nil
进行比较。
channel
channel是可以比较的,如果两个通道值是由同一个 make 调用创建的,则它们相等。
struct 的比较
-
同一 struct 的实例可以比较吗?
type S struct { Name string Age int Address *int } func main() { a := S{Name: "aa", Age: 1, Address: new(int)} b := S{Name: "aa", Age: 1, Address: new(int)} fmt.Println(a == b) // 输出false }
如果给结构体S增加一个Slice类型的成员变量后又是什么情况呢?
type S struct { Name string Age int Address *int Nums []int } func main() { a := S{Name: "aa", Age: 1, Address: new(int), Nums: []int{1, 2, 3, 4}} b := S{Name: "aa", Age: 1, Address: new(int), Nums: []int{1, 2, 3, 4}} fmt.Println(a == b) // invalid operation: a == b (struct containing []int cannot be compared) }
所以结论:同一个 struct 的两个实例可比较也不可比较,当结构不包含不可直接比较成员变量时可直接比较,否则不可直接比较。
-
reflect.DeepEqual
当需要对含有不可直接比较的数据类型的结构体实例进行比较时,我们可以借助 reflect.DeepEqual 函数 来对两个变量进行比较:type S struct { Name string Age int Address *int Nums []int } func main() { a := S{Name: "aa", Age: 1, Address: new(int), Nums: []int{1, 2, 3, 4}} b := S{Name: "aa", Age: 1, Address: new(int), Nums: []int{1, 2, 3, 4}} fmt.Println(reflect.DeepEqual(a, b)) // 输出为true }
interface 比较
interface 在某些场景下可以比较。
- 不带方法的 interface:
type Fooer interface { } type Barer interface { } func main() { var foo Fooer var bar Barer fmt.Println(foo == bar) // 输出true fooInstance := 1 barInstance := 1 fmt.Println(fooInstance == barInstance) // 输出为true fooInstance2 := 1 barInstance2 := 10 fmt.Println(fooInstance2 == barInstance2) // 输出为false }
- 带有方法的 interface,且方法名相同:
type Fooer interface { value() int } type Barer interface { value() int } type Foo int func (foo Foo) value() int { return 1 } type Bar int func (bar Bar) value() int { return 1 } func main() { var foo Fooer var bar Barer fmt.Println(foo == bar) // 输出true fooInstance := Foo(10) barInstance := Bar(10) fmt.Println(fooInstance == barInstance) // invalid operation: fooInstance == barInstance (mismatched types Foo and Bar) }
- 带有方法的 interface,且方法名不同:
type Fooer interface { FooerValue() int } type Barer interface { BarerValue() int } type Foo int func (foo Foo) FooerValue() int { return 1 } type Bar int func (bar Bar) BarerValue() int { return 1 } func main() { var foo Fooer var bar Barer fmt.Println(foo == bar) // invalid operation: foo == bar (mismatched types Fooer and Barer) fooInstance := Foo(10) barInstance := Bar(10) fmt.Println(fooInstance == barInstance) // invalid operation: fooInstance == barInstance (mismatched types Foo and Bar) }
- interface 和 nil 比较
type Fooer interface { FooerValue() int } type Foo int func (foo Foo) FooerValue() int { return 1 } func main() { var foo Fooer fmt.Println(nil == foo) // true fooInstance := Foo(10) fmt.Println(nil == fooInstance) // invalid operation: fooInstance == barInstance (mismatched types Foo and Bar) }
网友评论