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:
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.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。