golang擷取VARIANT 資料型別

來源:互聯網
上載者:User

如果某個函數的入參是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,該變數的介面值在記憶體裡是這樣的:

那麼對於第三種,類型斷言是怎麼判斷是不是某個介面呢?回到最初,在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}

 

 查看原文地址
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.