Home  >  Article  >  Backend Development  >  Analyze type comparison in go

Analyze type comparison in go

藏色散人
藏色散人forward
2021-06-21 16:09:533350browse

The following tutorial column of golang will introduce to you the analysis of type comparison in go. I hope it will be helpful to friends in need!

Overview

In a recent interview, the interviewer asked about the types between go In comparison, the answer is not very good. Fundamentally speaking, the foundation is not solid enough! I read a bunch of information on the Internet and made some simple summaries myself, haha!

Types in go

First let’s take a look at the most basic centralized types included in go

  • Basic types: The most basic types in go include integers (int, uint, int8, uint8, int16, uint16, int32, uint32, int64, uint64, byte, rune, etc.), floating point type (float32, float64), string (string is also a []rune array) and a less commonly used plural type (complex64/complex128).
  • Composite type: mainly includes structure and array.
  • Reference types: Slice, Map, Channel, pointer.
  • Interface type: Error, io.Reader, etc..

As a strongly typed language, go will not automatically help us perform type conversion with high-level languages ​​such as PHP, so we must use == when comparing. The types on both sides must be consistent. Even if their bottom types are the same. Look at the code below

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)
}

So go will not do implicit conversion for us. Even if the underlying types are consistent, they cannot be compared.
Next we analyze whether comparisons can be made from different types.

Basic type

The basic type of go is relatively simple. As long as the type is the same, then they can be compared. For example:

package main
import "fmt"
func main() {
    var a int = 0
    var b int = 1
    // 输出false
    fmt.Println(a == b)
}

But in the basic type Also note that the comparison of floating point types is not the same as in reality. For example, the result of 0.1 0.2 in calculation is not 0.3, but 0.30000000000000004.

package main
import "fmt"

func main() {
    var a float64=0.1
    var b float64=0.2
    // 0.30000000000000004
    fmt.Println(a+b)
}

Why is this? You can look at draveness( https://github.com/draveness) This article by the boss https://draveness.me/whys-the...

Compound type

Array

The difference between go arrays and slices is often asked in interviews. The length of an array in Go must be determined first, that is, the length cannot be expanded. And it is a value copy. If the parameters are passed to a function and modified, the external value will remain the same. Slice is the opposite. So whether arrays can be compared, look at the following example:

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)
}

It can be seen that arrays of the same length can be compared, but arrays of different lengths cannot be compared. what is the reason? This is because in the array type, the length of the array is also part of the type. Arrays of different lengths are considered to have different types, so they cannot be compared.

Structure

The same Struct is the same. The comparison of Struct also starts from the internal type, and the values ​​of each type are equal only when they are equal. The following example:

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
}

So it can be understood that Struct structures can be compared. Let’s look at another example: How did

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)
}

become incomparable again? This depends on the reference type below.

Reference type

The above example structure cannot be compared with slices. In go, Slice and Map are defined as Types that cannot be compared. Let's look at

If Slice is comparable, then what is used to define the same slice? If you use an address, what if the Slice pointed to by the two addresses is the same? This is obviously inappropriate. If it is the same as the array, then if I expand the slice, it will not be equal. Therefore, length and capacity are difficult to compare. Although this problem can be solved at the language level, the golang team believes that it is not worth the effort. Therefore Slice is regarded as incomparable.
The same Map is also defined as an incomparable type. So are reference types incomparable? No, look at an example:

package main
import "fmt"
type A struct {
    id int
    name string
}
func main() {
    a := &A { a : 1, b : "test1" }
    b := &A { a : 1, b : "test1" }
    c := a
    fmt.Println(a == b) // false
    fmt.Println(a == c) // true
    ch1 := make(chan int, 1)
    ch2 := make(chan int, 1)
    ch3 := ch1
    fmt.Println(ch1 == ch2) // false
    fmt.Println(ch1 == ch3) // true
}

Reference type variables store the memory address of a certain variable. Therefore, the comparison of reference type variables determines whether the two reference types store the same variable.

  • If it is the same variable, the memory address must be the same, then the reference type variables are equal, and "==" is used to determine true
  • If they are not the same variable, the memory The addresses are definitely different, and the "==" result is false

Interface type

Go language divides interface types into two categories according to whether the interface type contains a set of methods:

  • 使用 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

ac类型相同(都是int),值也相同(都是0,基本类型比较),故两者相等。 ab类型相同,值不等,故两者不等。 ad类型不同,aintdfloat64,故两者不等。

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

ab类型相同(都是A),值也相同(结构体A),故两者相等。 ac类型相同,值不同,故两者不等。 de类型相同(都是*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)

ab的类型是切片类型,而切片类型不可比较,所以a == bpanic

接口值的比较不要求接口类型(注意不是动态类型)完全相同,只要一个接口可以转化为另一个就可以比较。例如:

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
  • 复合类型中如果带有不可比较的类型,那么该类型也是不可比较的。可以理解不可比较类型具有传递性。

The above is the detailed content of Analyze type comparison in go. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:segmentfault.com. If there is any infringement, please contact admin@php.cn delete