go 的反射

go 中的 interface 有两个用途:
1、是接口定义约束
2、interface{}万能类型

interface 定义是这样的:

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

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

interface 变量定义是一个 16 个字节的结构体,首 8 字节是类型字段,后 8 字节是数据指针。
普通的 interface 是 iface 结构。而interface{} 对应的是 eface 结构;

从 interface{} 中得出真实类型
func actualType(model interface{}) {
    val := reflect.ValueOf(model)
    typ := reflect.Indirect(val).Type()
    fmt.Println(typ, val)
}

type Foo struct {
    i int32
}

func main() {
    actualType(10)
    actualType(Foo{})
}

输出:


image.png
interface 和 nil 的比较踩坑
type Worker interface {
    Work() error
}

type Qstruct struct{}

func (q *Qstruct) Work() error {
    return nil
}

// 返回一个 nil 
func findSomething() *Qstruct {
    return nil
}

func main() {
    var v Worker

    v = findSomething()
    if v != nil {
        // 走的是这个分支
        fmt.Printf("v(%v) != nil\n", v)
    } else {
        fmt.Printf("v(%v) == nil\n", v)
    }
}

前置知识:

  1. interface 变量新创建的时候是 nil ,则这 16 个字节是全 0 值;
  2. interface 变量的 nil 判断,逻辑是判断首 8 字节是否是 0 值;

关键就是 v = findSomething() 这行代码。这个是一个赋值操作,左边是一个接口变量,函数 findSomething 返回的是一个具体类型指针。所以,它一定会把接口变量 iface 前 8 字节设置非零字段的,因为有具体类型(无论具体类型是否是 nil 指针)。

你可能感兴趣的:(go 的反射)