警告:一个包含nil指针的接口不是nil接口

看 go语言圣经 上举的例子,看得一头雾水
已邀请:

simple - 既要有梦想,又要有实力

赞同来自: boyxiaolong Xargin kodango

可以把 inferface 类型的变量 理解为 一个“容器”,该“容器“”将包含赋值给该变量的值的 实际类型信息 和 值信息,**只有inferface变量的 类型信息 和 值信息 两部分都为nil,该接口才被称为 nil接口**。
如 var i interface{} = 100 , 可以简单的认为 接口变量i里面类型信息为"int", 值信息为“100”。
再如
var s Student // s == nil
var i interface{} = s
可以简单的认为 接口变量i里面类型信息为"Student", 值信息为 nil, 但 i不等于 nil。
如果想透彻理解,还是需要去看看 interface 的底层数据结构

CurveSoft - 70后Go爱好者

赞同来自: tangmo tsingson

简单的理解可以理解成“带类型信息的nil,不带类型信息的nil”

qiangmzsx - 痛而不言,笑而不语,迷而不失,惊而不乱。

赞同来自: haohongfan

```
package main

import (
"fmt"
)

type People interface {
Show()
}

type Student struct{}

func (stu *Student) Show() {

}

func live() People {
var stu *Student
return stu
}

func main() {
if live() == nil {
fmt.Println("AAAAAAA")
} else {
fmt.Println("BBBBBBB")
}
}
```
考点:interface内部结构
解答:
很经典的题! 这个考点是很多人忽略的interface内部结构。 go中的接口分为两种一种是空的接口类似这样:

var in interface{}
另一种如题目:
```
type People interface {
Show()
}
```
他们的底层结构如下:
```
type eface struct { //空接口
_type *_type //类型信息
data unsafe.Pointer //指向数据的指针(go语言中特殊的指针类型unsafe.Pointer类似于c语言中的void*)
}
type iface struct { //带有方法的接口
tab *itab //存储type信息还有结构实现方法的集合
data unsafe.Pointer //指向数据的指针(go语言中特殊的指针类型unsafe.Pointer类似于c语言中的void*)
}
type _type struct {
size uintptr //类型大小
ptrdata uintptr //前缀持有所有指针的内存大小
hash uint32 //数据hash值
tflag tflag
align uint8 //对齐
fieldalign uint8 //嵌入结构体时的对齐
kind uint8 //kind 有些枚举值kind等于0是无效的
alg *typeAlg //函数指针数组,类型实现的所有方法
gcdata *byte
str nameOff
ptrToThis typeOff
}
type itab struct {
inter *interfacetype //接口类型
_type *_type //结构类型
link *itab
bad int32
inhash int32
fun [1]uintptr //可变大小 方法集合
}
```
可以看出iface比eface 中间多了一层itab结构。 itab 存储_type信息和[]fun方法集,从上面的结构我们就可得出,因为data指向了nil 并不代表interface 是nil, 所以返回值并不为空,这里的fun(方法集)定义了接口的接收规则,在编译的过程中需要验证是否实现接口 结果:

BBBBBBB

boyxiaolong

赞同来自: yeyuqiu

```go
package main

import (
"fmt"
)

type People interface {
Show()
}

type Student struct{}

func (stu *Student) Show() {

}

func live() *Student {
var stu *Student
return stu
}

func main() {
if live() == nil {
fmt.Println("AAAAAAA")
} else {
fmt.Println("BBBBBBB")
}
}
```

如果live返回的是结构体,那也就是nil,如果返回的是接口,就是非nil,但数据是nil的,感谢啦!

tupunco

赞同来自: tangmo

把一个东西 赋值给 `interface{}` 其实 `装箱` 了一层.
The article you share here is great. I really like and appreciate your work. I read your article deeply, the points you mentioned in this article are very helpful thanks for sharing.
[word games online](https://word-games.online "word games online")
这是一件好事,我想每个人都觉得这些信息非常有价值,谢谢 [candy crush soda](https://candycrushsoda.co "candy crush soda")

要回复问题请先登录注册