# How to determine whether the value of an interface {} is nil

Posted by Brink Kale on Wed, 05 Jan 2022 18:46:42 +0100

Before we start, let's ask you a classic Go question: how to judge whether the value of an interface {} is nil?

This is also a question that may be asked in the interview. This question is very "mysterious". Friends who usually don't pay special attention can easily be cut here.

I believe many people will answer subconsciously. Wouldn't it be good to judge directly?

I thought so a long time ago, but after writing a demo, I found that things were not so simple.

Take a look at the following code, and you can guess the output first.

`package mainimport (    "fmt")func main()  {    var a *string = nil    var b interface{} = a    fmt.Println(b==nil) }`

The output result is false

Why? Next, we're going to talk about it.

## # 1. Comparison of two interface s

The internal implementation of interface contains two fields, one is type and the other is data

For such a variable

`var age interface{} = 25`

In fact, the internal structure is

Therefore, the comparison between the two interface s is bound to be related to these two fields.

After verification, the two interface s will be equal only in the following two cases.

### First case

Both type and data are equal

In the following code, the type of p1 and p2 is Profile, and the data is {"iswbm"}, so p1 and p2 are equal

Although the types of p3 and p3 are both * Profile, because data stores the address of the structure, and the two addresses and are different, p3 and p4 are not equal

`package mainimport "fmt"type Profile struct {    Name string}type ProfileInt interface {}func main()  {    var p1, p2 ProfileInt = Profile{"iswbm"}, Profile{"iswbm"}    var p3, p4 ProfileInt = &Profile{"iswbm"}, &Profile{"iswbm"}    fmt.Printf("p1 --> type: %T, data: %v \n", p1, p1)    fmt.Printf("p2 --> type: %T, data: %v \n", p2, p2)    fmt.Println(p1 == p2)  // true    fmt.Printf("p3 --> type: %T, data: %p \n", p3, p3)    fmt.Printf("p4 --> type: %T, data: %p \n", p4, p4)    fmt.Println(p3 == p4)  // false}`

After operation, the output is as follows

`p1 --> type: main.Profile, data: {iswbm} p2 --> type: main.Profile, data: {iswbm} truep3 --> type: *main.Profile, data: 0xc00008e200 p4 --> type: *main.Profile, data: 0xc00008e210 false`

### The second case

Special case: both interface s are nil

When the type and data of an interface are in unset state, the type and value of the interface are nil

`package mainimport "fmt"func main() {    var p1, p2 interface{}    fmt.Println(p1 == p2)  // true    fmt.Println(p1 == nil) // true}`

## # 2. interface vs. non interface

When an interface is compared with a non interface, the non interface will be converted into an interface, and then the comparison will be performed according to the rule of {two interface comparison}.

Examples are as follows

`package mainimport (    "fmt"    "reflect")func main()  {    var a string = "iswbm"    var b interface{} = "iswbm"    fmt.Println(a==b) // true}`

The above example may be easy to understand, so please look at the following example (the example at the beginning of the article). Why is b not equal to nil?

`package mainimport (    "fmt")func main()  {    var a *string = nil    var b interface{} = a    fmt.Println(b==nil) // false}`

But when you use ， b==nil ， the nil on the right is not simply that the value we understand is nil, but the correct understanding should be that the type is nil and the value is also nil.

Go will first convert nil to interface (type=nil, data=nil), which is the same as b (type=*string, data=nil). Although the data is the same, the types are not equal, so they are not equal.

Is there any way to judge whether an interface {} is nil?

There are ways, but with the help of reflection, a reflect package that will not be used as a last resort.

`package mainimport (    "fmt"    "reflect")func IsNil(i interface{}) bool {    vi := reflect.ValueOf(i)    if vi.Kind() == reflect.Ptr {        return vi.IsNil()    }    return false}func main() {    var a *string = nil    var b interface{} = a    fmt.Println(IsNil(b))}`

This paper introduces some internal implementation principles of Go during comparison through some examples. For many people, it may be a "new" knowledge. If they do not master it, they will dig a "big pit" for themselves in the coding process in the future. However, the "pit" in this language is not known or unknown. It is difficult to find it no matter how to check the code. I hope to take you to fill in this "pit" through this article.

This article originally belongs to the Go interview question bank column series. In the past, it was stated in the title that it was an interview question. Considering that some people have not been in the interview recently, they are afraid that you will miss such knowledge that you should master even if you don't interview. In the future, it may not be specially marked as an interview question in the title.

I have published this column series on Github: https://github.com/iswbm/golang-interview

This number has no message function. If there is something wrong with the article, you can go there and submit the issue to help me correct it. By the way, can you order me a small one ⭐⭐， There I sorted the question bank to facilitate index search.

Come on. See you next time

Topics: Go