zoukankan      html  css  js  c++  java
  • golang获取变量数据类型

    如果某个函数的入参是interface{},有下面几种方式可以获取入参的方法:

    1 fmt:

    import "fmt"
    func main() {
        v := "hello world"
        fmt.Println(typeof(v))
    }
    func typeof(v interface{}) string {
        return fmt.Sprintf("%T", v)
    }

    2 反射:

    import (
        "reflect"
        "fmt"
    )
    func main() {
        v := "hello world"
        fmt.Println(typeof(v))
    }
    func typeof(v interface{}) string {
        return reflect.TypeOf(v).String()
    }

    3 类型断言:

    func main() {
        v := "hello world"
        fmt.Println(typeof(v))
    }
    func typeof(v interface{}) string {
        switch t := v.(type) {
        case int:
            return "int"
        case float64:
            return "float64"
        //... etc
        default:
            _ = t
            return "unknown"
        }
    }

    其实前两个都是用了反射,fmt.Printf(“%T”)里最终调用的还是reflect.TypeOf()

    func (p *pp) printArg(arg interface{}, verb rune) {
        ...
        // Special processing considerations.
        // %T (the value's type) and %p (its address) are special; we always do them first.
        switch verb {
        case 'T':
            p.fmt.fmt_s(reflect.TypeOf(arg).String())
            return
        case 'p':
            p.fmtPointer(reflect.ValueOf(arg), 'p')
            return
        }

    reflect.TypeOf()的参数是v interface{},golang的反射是怎么做到的呢?

    在golang中,interface也是一个结构体,记录了2个指针:

    • 指针1,指向该变量的类型
    • 指针2,指向该变量的value

    如下,空接口的结构体就是上述2个指针,第一个指针的类型是type rtype struct;非空接口由于需要携带的信息更多(例如该接口实现了哪些方法),所以第一个指针的类型是itab,在itab中记录了该变量的动态类型: typ *rtype

    // emptyInterface is the header for an interface{} value.
    type emptyInterface struct {
        typ  *rtype
        word unsafe.Pointer
    }
    
    // nonEmptyInterface is the header for a interface value with methods.
    type nonEmptyInterface struct {
        // see ../runtime/iface.go:/Itab
        itab *struct {
            ityp   *rtype // static interface type
            typ    *rtype // dynamic concrete type
            link   unsafe.Pointer
            bad    int32
            unused int32
            fun    [100000]unsafe.Pointer // method table
        }
        word unsafe.Pointer
    }

    我们来看看reflect.TypeOf():

    // TypeOf returns the reflection Type that represents the dynamic type of i.
    // If i is a nil interface value, TypeOf returns nil.
    func TypeOf(i interface{}) Type {
        eface := *(*emptyInterface)(unsafe.Pointer(&i))
        return toType(eface.typ)
    }

    TypeOf看到的是空接口interface{},它将变量的地址转换为空接口,然后将将得到的rtype转为Type接口返回。需要注意,当调用reflect.TypeOf的之前,已经发生了一次隐式的类型转换,即将具体类型的向空接口转换。这个过程比较简单,只要拷贝typ *rtypeword unsafe.Pointer就可以了。

    例如w := os.Stdout,该变量的接口值在内存里是这样的:

    A *os.File interface value

    那么对于第三种,类型断言是怎么判断是不是某个接口呢?回到最初,在golang中,接口是一个松耦合的概念,一个类型是不是实现了某个接口,就是看该类型是否实现了该接口要求的所有函数,所以,类型断言判断的方法就是检查该类型是否实现了接口要求的所有函数。

    走读k8s代码的时候,可以看到比较多的类型断言的用法:

    func LeastRequestedPriorityMap(pod *api.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (schedulerapi.HostPriority, error) {
        var nonZeroRequest *schedulercache.Resource
        if priorityMeta, ok := meta.(*priorityMetadata); ok {
            nonZeroRequest = priorityMeta.nonZeroRequest
        } else {
            // We couldn't parse metadata - fallback to computing it.
            nonZeroRequest = getNonZeroRequests(pod)
        }
        return calculateUnusedPriority(pod, nonZeroRequest, nodeInfo)
    }

    类型断言的实现在src/runtime/iface.go里(?),不过这块代码没看懂,等以后再更新吧。

    func assertI2I2(inter *interfacetype, i iface) (r iface, b bool) {
        tab := i.tab
        if tab == nil {
            return
        }
        if tab.inter != inter {
            tab = getitab(inter, tab._type, true)
            if tab == nil {
                return
            }
        }
        r.tab = tab
        r.data = i.data
        b = true
        return
    }
    
    func assertE2I2(inter *interfacetype, e eface) (r iface, b bool) {
        t := e._type
        if t == nil {
            return
        }
        tab := getitab(inter, t, true)
        if tab == nil {
            return
        }
        r.tab = tab
        r.data = e.data
        b = true
        return
    }
     查看原文地址
  • 相关阅读:
    codeforces 57C 思维
    FOJ 2232 匈牙利算法找二分图最大匹配
    UVA 101 vector
    POJ 3070 矩阵mob
    codeforces 60B bfs
    codeforces 54A
    codeforces 466C 计数 codeforces 483B 二分 容斥
    FOJ 2213 简单几何
    CCF-最优配餐(BFS)
    杂论-FTP
  • 原文地址:https://www.cnblogs.com/xbblogs/p/9489489.html
Copyright © 2011-2022 走看看