# go语言的比较运算

CodeGeek · · 7249 次点击 · · 开始浏览

# 可赋值

A value x is assignable to a variable of type T ("x is assignable to T") in any of these cases:

• x's type is identical to T.
• x's type V and T have identical underlying types and at least one of V or T is not a defined type.
• T is an interface type and x implements T.
• x is a bidirectional channel value, T is a channel type, x's type V and T have identical element types, and at least one of V or T is not a defined type.
• x is the predeclared identifier nil and T is a pointer, function, slice, map, channel, or interface type.
• x is an untyped constant representable by a value of type T.

# 可比较

1. 可比较，包括相等(==)，和不相等(!=)
2. 可排序，包括大于(>)，大于等于(>=)，小于(>)，小于等于(<=)

1. 可排序的数据类型有三种，Integer，Floating-point，和String
2. 可比较的数据类型除了上述三种外，还有Boolean，Complex，Pointer，Channel，Interface，Struct，和Array
3. 不可比较的数据类型包括，Slice, Map, 和Function

# 可赋值和可比较的关系

In any comparison, the first operand must be assignable to the type of the second operand, or vice versa.

# 举例struct类型的比较

Struct values are comparable if all their fields are comparable. Two struct values are equal if their corresponding non-blank fields are equal.

## 例子1：类型是否相同问题

``````package main

import "fmt"

type T1 struct { name string }
type T2 struct { name string }

func main() {
v11 := T1 { "foo" }
v12 := T1 { "foo" }
v21 := T2 { "foo" }
v22 := T2 { "foo" }

fmt.Printf("v11 == v12 is %v\n", v11 == v12)    // output: v11 == v12 is true
//fmt.Printf("v11 == v21 is %v\n", v11 == v21)    // compile error, invalid operation: v11 == v21 (mismatched types T1 and T2)
//fmt.Printf("v11 == v22 is %v\n", v11 == v22)    // compile error, invalid operation: v11 == v22 (mismatched types T1 and T2)

//fmt.Printf("v12 == v21 is %v\n", v12 == v21)    // compile error, invalid operation: v12 == v21 (mismatched types T1 and T2)
//fmt.Printf("v12 == v22 is %v\n", v12 == v22)    // compile error, invalid operation: v12 == v22 (mismatched types T1 and T2)

fmt.Printf("v21 == v22 is %v\n", v21 == v22)    // output: v21 == v22 is true
}

``````

``````package main

import "fmt"

type Int int

func main() {
var v11 int = 1
var v12 int = 1
var v21 Int = 1
var v22 Int = 1

fmt.Printf("v11 == v12 is %v\n", v11 == v12)    // output: v11 == v12 is true
//fmt.Printf("v11 == v21 is %v\n", v11 == v21)    // compile error, invalid operation: v11 == v21 (mismatched types int and Int)
//fmt.Printf("v11 == v22 is %v\n", v11 == v22)    // compile error, invalid operation: v11 == v22 (mismatched types int and Int)

//fmt.Printf("v12 == v21 is %v\n", v12 == v21)    // compile error, invalid operation: v12 == v21 (mismatched types int and Int)
//fmt.Printf("v12 == v22 is %v\n", v12 == v22)    // compile error, invalid operation: v12 == v22 (mismatched types int and Int)

fmt.Printf("v21 == v22 is %v\n", v21 == v22)    // output: v21 == v22 is true
}
``````

## 例子2：是否所有的域(field)都可比较

``````package main

import "fmt"

type T1 struct { name string }
type T2 struct { name string; attrs map[string]interface{} }

func main() {
v11 := T1 { "foo" }
v12 := T1 { "foo" }
v21 := T2 { "foo", make(map[string]interface{}) }
v22 := T2 { "foo", make(map[string]interface{}) }

fmt.Printf("v11 == v12 is %v\n", v11 == v12)    // output: v11 == v12 is true
fmt.Printf("v21 == v22 is %v\n", v21 == v22)    // compile error: invalid operation: v21 == v22 (struct containing map[string]interface {} cannot be compared)
}
``````

## 例子3：包含空域(Blank Field)

``````package main

import "fmt"

type T1 struct {
i int64
j int32
_ int32
}

// You cannot set or get a blank field; it cannot be refered.
// You can't do it in a composite literal either.
// The only use for a blank field in a struct is for padding.

func main() {
v11 := T1 { i:10, j:10 }
v12 := T1 { i:10, j:10 }

fmt.Printf("v11 == v12 is %v\n", v11 == v12)    // output: v11 == v12 is true
}
``````

## 例子4：匿名类型比较

go语言定义了两种类型：命名类型，和匿名类型。

``````package main

import "fmt"
import "reflect"

type T1 struct { name string }
type T2 struct { name string }

func main() {
v1 := T1 { "foo" }
v2 := T2 { "foo" }
v3 := struct{ name string } {"foo"}
v4 := struct{ name string } {"foo"}

fmt.Println("v1: type=", reflect.TypeOf(v1), "value=", reflect.ValueOf(v1)) // v1: type= main.T1 value= {foo}
fmt.Println("v2: type=", reflect.TypeOf(v2), "value=", reflect.ValueOf(v2)) // v2: type= main.T2 value= {foo}
fmt.Println("v3: type=", reflect.TypeOf(v3), "value=", reflect.ValueOf(v3)) // v3: type= struct { name string } value= {foo}
fmt.Println("v4: type=", reflect.TypeOf(v4), "value=", reflect.ValueOf(v4)) // v4: type= struct { name string } value= {foo}

//fmt.Println(v1 == v2) // compiler error: invalid operation: v1 == v2 (mismatched types T1 and T2)
fmt.Println(v1 == v3)   // true, why? their type is different
fmt.Println(v2 == v3)   // true, why?
fmt.Println(v3 == v4)   // true
}
``````

Struct values are comparable if all their fields are comparable. Two struct values are equal if their corresponding non-blank fields are equal.

In any comparison, the first operand must be assignable to the type of the second operand, or vice versa.

## 总结：struct的比较

struct的比较只需要满足两个条件：

1. 从所有比较操作继承下来的规则，即两个变量必须是可赋值的。
2. 针对struct本身的规则，即struct的所有域必须都是可比较的；注意这里并不管struct本身的定义类型。

0 回复

• 请尽量让自己的回复能够对别人有帮助
• 支持 Markdown 格式, **粗体**、~~删除线~~、``单行代码``
• 支持 @ 本站用户；支持表情（输入 : 提示），见 Emoji cheat sheet
• 图片支持拖拽、截图粘贴等方式上传

# 可赋值

A value x is assignable to a variable of type T ("x is assignable to T") in any of these cases:

• x's type is identical to T.
• x's type V and T have identical underlying types and at least one of V or T is not a defined type.
• T is an interface type and x implements T.
• x is a bidirectional channel value, T is a channel type, x's type V and T have identical element types, and at least one of V or T is not a defined type.
• x is the predeclared identifier nil and T is a pointer, function, slice, map, channel, or interface type.
• x is an untyped constant representable by a value of type T.

# 可比较

1. 可比较，包括相等(==)，和不相等(!=)
2. 可排序，包括大于(>)，大于等于(>=)，小于(>)，小于等于(<=)

1. 可排序的数据类型有三种，Integer，Floating-point，和String
2. 可比较的数据类型除了上述三种外，还有Boolean，Complex，Pointer，Channel，Interface，Struct，和Array
3. 不可比较的数据类型包括，Slice, Map, 和Function

# 可赋值和可比较的关系

In any comparison, the first operand must be assignable to the type of the second operand, or vice versa.

# 举例struct类型的比较

Struct values are comparable if all their fields are comparable. Two struct values are equal if their corresponding non-blank fields are equal.

## 例子1：类型是否相同问题

``````package main

import "fmt"

type T1 struct { name string }
type T2 struct { name string }

func main() {
v11 := T1 { "foo" }
v12 := T1 { "foo" }
v21 := T2 { "foo" }
v22 := T2 { "foo" }

fmt.Printf("v11 == v12 is %v\n", v11 == v12)    // output: v11 == v12 is true
//fmt.Printf("v11 == v21 is %v\n", v11 == v21)    // compile error, invalid operation: v11 == v21 (mismatched types T1 and T2)
//fmt.Printf("v11 == v22 is %v\n", v11 == v22)    // compile error, invalid operation: v11 == v22 (mismatched types T1 and T2)

//fmt.Printf("v12 == v21 is %v\n", v12 == v21)    // compile error, invalid operation: v12 == v21 (mismatched types T1 and T2)
//fmt.Printf("v12 == v22 is %v\n", v12 == v22)    // compile error, invalid operation: v12 == v22 (mismatched types T1 and T2)

fmt.Printf("v21 == v22 is %v\n", v21 == v22)    // output: v21 == v22 is true
}

``````

``````package main

import "fmt"

type Int int

func main() {
var v11 int = 1
var v12 int = 1
var v21 Int = 1
var v22 Int = 1

fmt.Printf("v11 == v12 is %v\n", v11 == v12)    // output: v11 == v12 is true
//fmt.Printf("v11 == v21 is %v\n", v11 == v21)    // compile error, invalid operation: v11 == v21 (mismatched types int and Int)
//fmt.Printf("v11 == v22 is %v\n", v11 == v22)    // compile error, invalid operation: v11 == v22 (mismatched types int and Int)

//fmt.Printf("v12 == v21 is %v\n", v12 == v21)    // compile error, invalid operation: v12 == v21 (mismatched types int and Int)
//fmt.Printf("v12 == v22 is %v\n", v12 == v22)    // compile error, invalid operation: v12 == v22 (mismatched types int and Int)

fmt.Printf("v21 == v22 is %v\n", v21 == v22)    // output: v21 == v22 is true
}
``````

## 例子2：是否所有的域(field)都可比较

``````package main

import "fmt"

type T1 struct { name string }
type T2 struct { name string; attrs map[string]interface{} }

func main() {
v11 := T1 { "foo" }
v12 := T1 { "foo" }
v21 := T2 { "foo", make(map[string]interface{}) }
v22 := T2 { "foo", make(map[string]interface{}) }

fmt.Printf("v11 == v12 is %v\n", v11 == v12)    // output: v11 == v12 is true
fmt.Printf("v21 == v22 is %v\n", v21 == v22)    // compile error: invalid operation: v21 == v22 (struct containing map[string]interface {} cannot be compared)
}
``````

## 例子3：包含空域(Blank Field)

``````package main

import "fmt"

type T1 struct {
i int64
j int32
_ int32
}

// You cannot set or get a blank field; it cannot be refered.
// You can't do it in a composite literal either.
// The only use for a blank field in a struct is for padding.

func main() {
v11 := T1 { i:10, j:10 }
v12 := T1 { i:10, j:10 }

fmt.Printf("v11 == v12 is %v\n", v11 == v12)    // output: v11 == v12 is true
}
``````

## 例子4：匿名类型比较

go语言定义了两种类型：命名类型，和匿名类型。

``````package main

import "fmt"
import "reflect"

type T1 struct { name string }
type T2 struct { name string }

func main() {
v1 := T1 { "foo" }
v2 := T2 { "foo" }
v3 := struct{ name string } {"foo"}
v4 := struct{ name string } {"foo"}

fmt.Println("v1: type=", reflect.TypeOf(v1), "value=", reflect.ValueOf(v1)) // v1: type= main.T1 value= {foo}
fmt.Println("v2: type=", reflect.TypeOf(v2), "value=", reflect.ValueOf(v2)) // v2: type= main.T2 value= {foo}
fmt.Println("v3: type=", reflect.TypeOf(v3), "value=", reflect.ValueOf(v3)) // v3: type= struct { name string } value= {foo}
fmt.Println("v4: type=", reflect.TypeOf(v4), "value=", reflect.ValueOf(v4)) // v4: type= struct { name string } value= {foo}

//fmt.Println(v1 == v2) // compiler error: invalid operation: v1 == v2 (mismatched types T1 and T2)
fmt.Println(v1 == v3)   // true, why? their type is different
fmt.Println(v2 == v3)   // true, why?
fmt.Println(v3 == v4)   // true
}
``````

Struct values are comparable if all their fields are comparable. Two struct values are equal if their corresponding non-blank fields are equal.

In any comparison, the first operand must be assignable to the type of the second operand, or vice versa.

## 总结：struct的比较

struct的比较只需要满足两个条件：

1. 从所有比较操作继承下来的规则，即两个变量必须是可赋值的。
2. 针对struct本身的规则，即struct的所有域必须都是可比较的；注意这里并不管struct本身的定义类型。