2
WeChat search [ brain into the fried fish ] follow this fried fish with liver-fried liver. This article GitHub github.com/eddycjy/blog has been included, and there are my series of articles, materials and open source Go books.

Hello everyone, I am fried fish.

Recently, it is the season of interviews. In my Go reader exchange group, many friends appeared in some Go interview questions that they encountered during the interview process.

Today’s male protagonist is a compulsory skill for Go engineers, and it is also a place that is very easy to step on. It is " Go Interview Question: Can Go structs be compared? "

If it can be compared, why? If it cannot be compared, why?

Please mute here the answer your mind, and then discuss a wave of Go technology philosophy with fried fish.

What is the structure

There is a basic type in the Go language, which developers call a struct. It is very commonly used in the Go language, the basic definition:

type struct_variable_type struct {
    member definition
    member definition
    ...
    member definition
}

Simple example:

package main

import "fmt"

type Vertex struct {
    Name1 string
    Name2 string
}

func main() {
    v := Vertex{"脑子进了", "煎鱼"}
    v.Name2 = "蒸鱼"
    fmt.Println(v.Name2)
}

Output result:

蒸鱼

This part is basic knowledge, so I won't explain it too much. If you don't understand, it is recommended to relearn the basics of Go language grammar.

Compare

Example one

Next, we will formally discuss the question of Go structure comparison. The first example is as follows:

type Value struct {
    Name   string
    Gender string
}

func main() {
    v1 := Value{Name: "煎鱼", Gender: "男"}
    v2 := Value{Name: "煎鱼", Gender: "男"}
    if v1 == v2 {
        fmt.Println("脑子进煎鱼了")
        return
    }

    fmt.Println("脑子没进煎鱼")
}

We declared two variables, v1 and v2. They are both Value structure, which are two instances of the same structure.

What is the result of their comparison, is it outputting "the brain is in the fried fish" or "the brain is not in the fried fish"?

Output result:

脑子进煎鱼了

The final output is "Fried fish in the brain". The preliminary conclusion is that the structure can be compared. Everyone is happy, then this article is about to end?

Of course not ... a lot of people stepped pit the Go language, truth is that the structure is comparable, nor comparable , do not go astray, this is a very "interesting" phenomenon.

Example two

Next, continue to modify the above example, we added pointer type references to the original structure.

The second example is as follows:

type Value struct {
    Name   string
    Gender *string
}

func main() {
    v1 := Value{Name: "煎鱼", Gender: new(string)}
    v2 := Value{Name: "煎鱼", Gender: new(string)}
    if v1 == v2 {
        fmt.Println("脑子进煎鱼了")
        return
    }

    fmt.Println("脑子没进煎鱼")
}

What is the output of this program? Let's guess that the variable is still two instances of the same structure, and the assignment method and content of the value are the same. Should it output "brain in fried fish"?

The answer is: no fried fish in the brain.

Example three

We continue to believe in evil and try other basic types to see if the results are still equal.

The third example is as follows:

type Value struct {
    Name   string
    GoodAt []string
}

func main() {
    v1 := Value{Name: "煎鱼", GoodAt: []string{"炸", "煎", "蒸"}}
    v2 := Value{Name: "煎鱼", GoodAt: []string{"炸", "煎", "蒸"}}
    if v1 == v2 {
        fmt.Println("脑子进煎鱼了")
        return
    }

    fmt.Println("脑子没进煎鱼")
}

What is the output of this program?

the answer is:

# command-line-arguments
./main.go:15:8: invalid operation: v1 == v2 (struct containing []string cannot be compared)

When the program runs, an error is reported directly, and the IDE also prompts an error, and no fried fish can be output.

Example four

Can different structures and the same value content be compared?

Fourth example:

type Value1 struct {
    Name string
}

type Value2 struct {
    Name string
}

func main() {
    v1 := Value1{Name: "煎鱼"}
    v2 := Value2{Name: "煎鱼"}
    if v1 == v2 {
        fmt.Println("脑子进煎鱼了")
        return
    }

    fmt.Println("脑子没进煎鱼")
}

Obviously, an error will be reported directly:

# command-line-arguments
./main.go:18:8: invalid operation: v1 == v2 (mismatched types Value1 and Value2)

Isn't it impossible to compare at all? No, we can do it with the help of forced conversion:

    if v1 == Value1(v2) {
        fmt.Println("脑子进煎鱼了")
        return
    }

In this way, the program will run normally, and output "Fried fish in the brain". Of course, if the type is not comparable, it is still impossible.

why

Why some of the Go structures are normal when compared, and some are not, and even errors are reported directly. Is there any "hidden rule"?

In the Go language, sometimes Go structures cannot be directly compared. When their basic types include slice, map, and function, they cannot be compared. If the comparison is forced, it will lead to a direct error in the example.

The pointer references, although they are all new(string) , are one thing from the appearance, but the specific return address is different.

Therefore, if you want to compare, you need to change to:

func main() {
    gender := new(string)
    v1 := Value{Name: "煎鱼", Gender: gender}
    v2 := Value{Name: "煎鱼", Gender: gender}
    ...
}

In this way, the comparison between the two can be guaranteed. What if we are forced to be helpless and asked to use structure comparisons?

At this time, the reflection method reflect.DeepEqual can be used, as follows:

func main() {
    v1 := Value{Name: "煎鱼", GoodAt: []string{"炸", "煎", "蒸"}}
    v2 := Value{Name: "煎鱼", GoodAt: []string{"炸", "煎", "蒸"}}
    if reflect.DeepEqual(v1, v2) {
        fmt.Println("脑子进煎鱼了")
        return
    }

    fmt.Println("脑子没进煎鱼")
}

In this way, the comparison can be made correctly, and the output result is "Fried fish in the brain".

The reflection comparison method reflect.DeepEqual used in the example is often used to determine whether two values are consistent in depth. The rules are as follows:

  • Values of the same type are equal in depth, and values of different types are never equal in depth.
  • When the corresponding elements of the array values are equal in depth, the array values are equal in depth.
  • When the struct value is equal in depth if its corresponding fields (including exported and unexported fields) are equal in depth, then the value is equal in depth.
  • When the function (func) values are all zero, the depth is equal; otherwise, the depth is not equal.
  • When the interface value holds a specific value with equal depth, the depth is equal.
  • ...

For more details, you can go to golang.org/pkg/reflect/#DeepEqual for a detailed view:

reflect.DeepEqual 完整说明

This method has performed compatible processing and identification of various types in the Go language. Since this is not the focus of this article, it will not be further expanded.

to sum up

In this article, we expand and explain specific examples of whether Go language structs can be compared.

In essence, it is still a problem of understanding the basic data types of the Go language, which can be regarded as a specific further expansion of the deformation into the structure.

I don't know if you have suffered any loss in the Go structure, please leave a message in the comment area below to communicate and discuss with us.

If you have any questions please comment and feedback exchange area, best relationship is mutual achievement , everybody thumbs is fried fish maximum power of creation, thanks for the support.

The article is continuously updated, and you can read it on [My brain is fried fish], and reply [160bda7dcb42b4 000 ] I have prepared the first-line interview algorithm question and information; this article GitHub github7.com/blogb has been included , Welcome Star to urge you to update.

煎鱼
8.4k 声望12.8k 粉丝