Golang中用==判断是否相等

本文介绍Go语言中 == 在一些常见场景下的判断逻辑。

基础类型与指针

对于基础类型和指针,== 符号都是直接判断值是否相等。

因为指针的值实际上是内存地址,所以对于指针是否相等的判断和c语言一样都是看指针是否指向同一个内存地址

// 基础类型: int, string等, 都是值比较
var i1 = 2
var i2 = 2
var s1 = "hello"
var s2 = "hello"
fmt.Println(i1 == i2 && s1 == s2) // true
fmt.Println(&i1 == &i2 || &s1 == &s2) // false

// 指针类型: 地址比较
var p1 = &i1
var p2 = &i2
var p3 = &i1
fmt.Println(p1 == p2) // false
fmt.Println(p1 == p3) // true

struct

  1. 两个不同的类型的值之间不能比较
  2. 相同类型的值进行比较时,根据结构体中每一项是否相等来判断值是否相等(如果结构体中嵌套子结构体,也会用相同的逻辑去比较子结构体)
type B struct {
	B1 int
	B2 int
}

type A struct {
	A1 int
	Bc B
}

type C A

func main() {
	a1 := A{A1: 1, Bc: B{B1: 1, B2: 1}}
	a2 := A{A1: 1, Bc: B{B1: 1, B2: 1}}
	a3 := A{A1: 1, Bc: B{B1: 1, B2: 2}}
	fmt.Println(a1 == a2)   // true
	fmt.Println(a2 == a3)   // false
	fmt.Println(&a1 == &a2) // false

	c := C{A1: 1, Bc: B{B1: 1, B2: 2}}
	fmt.Println(c == a3) // cannot compare c == a3 (mismatched types C and A)
}

interface

判断interface是否相等时,会分别判断

  1. 值的类型是否相同
  2. 值是否相同
type A int
type B = A
type C int
type I interface{ m() }

func (a A) m() {}
func (c C) m() {}
func main() {
	// A, B 是相同类型, C和A,B是不同类型
	var a I = A(1)
	var a1 I = A(2)
	var b I = B(1)
	var c I = C(1)
	fmt.Println(a == b)  // true
	fmt.Println(a == a1) // false, 类型相同值不同
	fmt.Println(b == c)  // false, 类型不同
}

chan

两个channel如果要相等,有两种情况

  1. 都为nil
  2. chan结构体中的值完全相等
var ch1, ch2 chan int
fmt.Println(ch1 == ch2) // true

ch1 = make(chan int)
ch2 = make(chan int)
fmt.Println(ch1 == ch2)   // false
ch2 = ch1                 // 发生了chan结构体的复制, ch2和ch1结构体虽然位于不同的地址, 但结构体中的值(包括一些指针的值)是完全相等的
fmt.Println(ch1 == ch2)   // true
fmt.Println(&ch1 == &ch2) // false, 它们指向不同的地址

array

要求

  1. 数组长度相同
  2. 数组中每一项的值相同
type T struct {
	name string
	age  int
	_    float64
}

func main() {
	x := [...]float64{1.1, 2, 3.14}
	fmt.Println(x == [...]float64{1.1, 2, 3.14}) // true
	y := [1]T{{"foo", 1, 0}}
	fmt.Println(y == [1]T{{"foo", 1, 1}}) // true
}

不可用 == 比较的类型 func, slice, map

它们即使类型相同也不能用==相互比较,它们只能和nil用 == 比较

func main() {
	f := func(int) int { return 1 }
	// g := func(int) int { return 2 }
	// f == g // cannot compare f == g (operator == not defined for func(int) int)

	m1 := make(map[int]int)
	// m2 := make(map[int]int)
	// m1 == m2 // cannot compare m1 == m2 (operator == not defined for map[int]int)

	var slice1 []int
	// var slice2 []int
	// slice1 == slice2 // cannot compare slice1 == slice2 (operator == not defined for []int)

	fmt.Println(f == nil)      // false
	fmt.Println(m1 == nil)     // false
	fmt.Println(slice1 == nil) // true
}

reflect.DeepEqual

对于map和slice,可以用reflect.DeepEqual来比较是否相等

m1 := make(map[int]int)
m2 := make(map[int]int)
fmt.Println(reflect.DeepEqual(m1, m2)) // true

var slice1 []int = []int{1, 2, 3}
var slice2 []int = []int{1, 2, 3}
fmt.Println(reflect.DeepEqual(slice1, slice2)) // true

但对于func类型,需要用reflect.TypeOf来判断函数是否相同

f := func(int) int { return 1 }
g := func(int) int { return 1 }
fmt.Println(reflect.DeepEqual(f, g))                // false
fmt.Println(reflect.TypeOf(f) == reflect.TypeOf(g)) // true

参考: https://medium.com/golangspec/equality-in-golang-ff44da79b7f1

posted @ 2022-02-10 18:09  elimsc  阅读(1758)  评论(0编辑  收藏  举报