警告:一个包含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 的底层数据结构

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

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{} 其实 装箱 了一层.

CurveSoft - 70后Go爱好者

赞同来自: tangmo

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

要回复问题请先登录注册