- 基本的な型: go の最も基本的な型には、整数 (
- int、uint、int8、uint8、int16、uint16、int32、uint32、int64、uint64、byte、rune
など)、浮動小数点型 (
float32、float64)、文字列(
stringは []rune 配列でもあります)、あまり一般的ではありませんが複数型 (
complex64/complex128) です。
複合タイプ: 主に - structural
と
arrayが含まれます。
参照タイプ: - スライス、マップ、チャネル、ポインター
。
インターフェイス タイプ: - エラー、io.Reader など。
。
== を使用する必要があります。たとえ底部のタイプが同じであっても、両側のタイプは一貫している必要があります。以下のコードを見てください
package main import "fmt" type A struct { Id int } type B struct { Id int } func main() { var a int var b int16 // 编译报错:invalid operation a == b (mismatched types int and int16) fmt.Println(a == b) aStruct := A{Id:5} bStruct := B{Id:5} // 编译报错:invalid operation: aStruct == bStruct (mismatched types A and B) fmt.Println(aStruct == bStruct) }
次に、異なるタイプから比較できるかどうかを分析します。
package main import "fmt" func main() { var a int = 0 var b int = 1 // 输出false fmt.Println(a == b) }
package main
import "fmt"
func main() {
var a float64=0.1
var b float64=0.2
// 0.30000000000000004
fmt.Println(a+b)
}
ログイン後にコピー
同じ長さの配列は比較できますが、異なる長さの配列は比較できないことがわかりますpackage main import "fmt" func main() { var a float64=0.1 var b float64=0.2 // 0.30000000000000004 fmt.Println(a+b) }
。理由は何ですか?これは、配列型では配列の長さも型の一部であるためで、長さが異なる配列は異なる型とみなされ、比較することができません。
構造同じ
は同じです。
Struct の比較も内部型から始まり、各型の値は等しい場合のみ等しくなります。以下の例: <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">package main
import "fmt"
func main() {
a := [2]int{1, 2}
b := [2]int{1, 2}
c := [2]int{1, 3}
d := [3]int{1, 2, 4}
fmt.Println(a == b) // true
fmt.Println(a == c) // false
fmt.Println(a == d) // invalid operation: a == d (mismatched types [2]int and [3]int)
}</pre><div class="contentsignin">ログイン後にコピー</div></div>
したがって、Struct
構造体を比較できることがわかります。別の例を見てみましょう。
package main import "fmt" type A struct { id int name string } func main() { a := A{id:5,name:"123"} b := A{id:5,name:"123"} c := A{id:5,name:"1234"} fmt.Println(a == b) // true fmt.Println(a == c) // false }
はどのようにして再び比類のないものになったのでしょうか?これは、以下の参照タイプによって異なります。 参照型
上記の例の構造はスライスと比較できません。goでは、
Sliceと
Mapが比較できない型として定義されています。 。 を見てみましょう。
Slice
が同等である場合、同じスライスを定義するために何が使用されますか?アドレスを使用する場合、2 つのアドレスが指す
が同じである場合はどうなるでしょうか?これは明らかに不適切です。配列と同じである場合、スライスを展開すると等しくなくなります。したがって、長さと容量を比較することは困難です。この問題は言語レベルで解決できますが、golang チームは、努力する価値はないと考えています。したがって、Slice
は比較不可能とみなされます。 同じ
Map も比較不可能な型として定義されています。参照型は比較できないのでしょうか? いいえ、例を見てください:
package main import "fmt" type A struct { id int name string son []int } func main() { a := A{id:5,name:"123",son:[]int{1,2,3}} b := A{id:5,name:"123",son:[]int{1,2,3}} fmt.Println(a == b) // invalid operation: a == b (struct containing []int cannot be compared) }
参照型変数には、特定の変数のメモリ アドレスが格納されます。したがって、参照型変数を比較すると、2 つの参照型が同じ変数を格納するかどうかが決まります。
同じ変数の場合、メモリ アドレスは同じである必要があり、参照型変数は等しいため、「==」を使用して true を判断します。Ifは同じ変数ではなく、メモリです。 アドレスは明らかに異なり、「==」の結果は false です。- インターフェイスの種類
- Go 言語では、インターフェイスの種類を次の 2 つのカテゴリに分類します。インターフェイス タイプに一連のメソッドが含まれているかどうか:
- 使用
runtime.iface
结构体表示包含方法的接口 - 使用
runtime.eface
结构体表示不包含任何方法的interface{}
类型
type eface struct { // 16 字节 _type *_type data unsafe.Pointer } type iface struct { // 16 字节 tab *itab data unsafe.Pointer }
所以我们可以得知,一个接口值是由两个部分组成的,即该接口对应的类型和接口对应具体的值。接口值的比较涉及这两部分的比较,只有当类型和值都相等(动态值使用==
比较),两个接口值才是相等的。看个例子:
var a interface{} = 0 var b interface{} = 2 var c interface{} = 0 var d interface{} = 0.0 fmt.Println(a == b) // false fmt.Println(a == c) // true fmt.Println(a == d) // false
a
和c
类型相同(都是int
),值也相同(都是0
,基本类型比较),故两者相等。 a
和b
类型相同,值不等,故两者不等。 a
和d
类型不同,a
为int
,d
为float64
,故两者不等。
type A struct { a int b string } var a interface{} = A { a: 1, b: "test" } var b interface{} = A { a: 1, b: "test" } var c interface{} = A { a: 2, b: "test" } fmt.Println(a == b) // true fmt.Println(a == c) // false var d interface{} = &A { a: 1, b: "test" } var e interface{} = &A { a: 1, b: "test" } fmt.Println(d == e) // false
a
和b
类型相同(都是A
),值也相同(结构体A
),故两者相等。 a
和c
类型相同,值不同,故两者不等。 d
和e
类型相同(都是*A
),值使用指针(引用)类型的比较,由于不是指向同一个地址,故不等。
不过需要注意的是,如果接口中类型是切片或者Map
不可比较的类型,那么会直接报错的。看个例子:
var a interface{} = []int{1, 2} var b interface{} = []int{1, 2} // panic: runtime error: comparing uncomparable type []int fmt.Println(a == b)
a
和b
的类型是切片类型,而切片类型不可比较,所以a == b
会panic
。
接口值的比较不要求接口类型(注意不是动态类型)完全相同,只要一个接口可以转化为另一个就可以比较。例如:
var f *os.File var r io.Reader = f var rc io.ReadCloser = f fmt.Println(r == rc) // true var w io.Writer = f // invalid operation: r == w (mismatched types io.Reader and io.Writer) fmt.Println(r == w)
r
的类型为io.Reader
接口,rc
的类型为io.ReadCloser
接口。查看源码,io.ReadCloser
的定义如下:
type ReadCloser interface { Reader Closer }
io.ReadCloser
可转化为io.Reader
,故两者可比较。
而io.Writer
不可转化为io.Reader
,编译报错。
总结
- 可比较:
int、ifloat、string、bool、complex、pointe、channel、interface、array
- 不可比较:
slice、map、function
- 复合类型中如果带有不可比较的类型,那么该类型也是不可比较的。可以理解不可比较类型具有传递性。