2
If you have any questions or suggestions, please communicate and collide in time. is [Fried fish in the brain], GitHub address: 1609f555de58b7 https://github.com/eddycjy .

Hello everyone, I am fried fish.

A few days ago, I saw a small partner in the reader exchange group, and had a lot of doubts about the use of interface.

Coincidentally, I also saw a small partner on the Internet when I was asked during a Go interview:

image.png

Today, I deliberately shared it to let everyone avoid this pit.

Example one

The first example, the following code:

func main() {
    var v interface{}
    v = (*int)(nil)
    fmt.Println(v == nil)
}

What do you think is the output?

the answer is:

false

Why not true . Obviously, it has been forcibly set to nil . Is there a problem with the Go compiler?

Example two

The second example, the following code:

func main() {
    var data *byte
    var in interface{}

    fmt.Println(data, data == nil)
    fmt.Println(in, in == nil)

    in = data
    fmt.Println(in, in == nil)
}

What do you think is the output?

the answer is:

<nil> true
<nil> true
<nil> false

This is even more strange, why the data and in variables just declared, the output result is nil , and the judgment result is also true .

How can the world change as soon as data is assigned to the variable in The output result is still nil , but the judgment becomes false .

The result is similar to the first example above, which is really amazing.

the reason

The fundamental reason for the difference between interface judgment and imagination is that interface is not a pointer type, although it looks alike, so that it misleads many people.

We drill down to interface, interface has two types of data structures:

  • runtime.eface structure: represents an empty interface that does not contain any methods, also known as empty interface.
  • runtime.iface structure: represents the interface containing the method.

Take a look at the corresponding underlying data structure of the two:

type eface struct {
    _type *_type
    data  unsafe.Pointer
}

type iface struct {
    tab  *itab
    data unsafe.Pointer
}

You will find that interface is not a simple value, but divided into type and value .

Therefore, the traditional perception that this nil is not that nil, must have both the type and value of nil, then the nil judgment of the interface will be true .

Solution

It is not so much a solution, as it is a tactful way to break the game. Without changing the type, one of the methods is to use reflect, as in the following code:

func main() {
    var data *byte
    var in interface{}

    in = data
    fmt.Println(IsNil(in))
}

func IsNil(i interface{}) bool {
    vi := reflect.ValueOf(i)
    if vi.Kind() == reflect.Ptr {
        return vi.IsNil()
    }
    return false
}

Use reflection to judge the value of nil, there will be special processing for the interface type in reflection, and the final output result is: true, to achieve the effect.

Other methods are to change the original program logic, for example:

  • The value is judged as nil, and then returned to the interface setting.
  • Return the specific value type instead of returning the interface.

to sum up

Go interface is one of the most commonly used types in the Go language. If you are used to if err != nil , you can easily step into it.

I suggest you keep your eyes on it. If you want to have a better understanding of interface, you can read this in-depth article of mine: "An article thoroughly understands the interface interface of Go language decryption".

Have your friends stepped on it or encountered interface-related "pits"? Welcome everyone to leave a message below to discuss and share.

Let's rush together!

My official account

Share Go language, microservice architecture and strange system design. Welcome everyone to follow my official account to communicate and communicate with me.

best relationship between . Your likes is fried fish . Thank you for your support.


煎鱼
8.4k 声望12.8k 粉丝