《The.Go.Programming.Language.2015.11》之 reflect

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

    • 判斷reflectValue類型並提取資料
    • addressable
    • 擷取結構體方法的名稱

判斷reflect.Value類型並提取資料

對於reflect.Value類型資料,根據Kind()進行判斷

func formatAtom(v reflect.Value) string {    switch v.Kind() {    case reflect.Invalid:        return "invalid"    case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int8, reflect.Int64:        return strconv.FormatInt(v.Int(), 10)    case reflect.Bool:        return strconv.FormatBool(v.Bool())    case reflect.String:        return v.String()    default:        return "no ex"    }}

對於其他複雜類型的資料

func display(path string, v reflect.Value) {    switch v.Kind() {    case reflect.Invalid:        fmt.Println("")    case reflect.Slice, reflect.Array:        for i := 0; i < v.Len(); i++ {            display(fmt.Sprintf("%s[%d]", path, i), v.Index(i))        }    case reflect.Struct:        for i := 0; i < v.NumField(); i++ {            fieldPath := fmt.Sprintf("%s[%s]", path, v.Type().Field(i).Name)            display(fieldPath, v.Field(i))        }    case reflect.Map:        for _, key := range v.MapKeys() {            display(fmt.Sprintf("[%s][%s]", path, formatAtom(key)), v.MapIndex(key))        }    default:        fmt.Printf("%s=%s\n", path, formatAtom(v))    }}

注意,對於結構體利用v.Type().Field(i).Name擷取網域名稱,利用v.Field(i)擷取域值。

addressable

利用CanAddr()成員判斷判斷是否addressable。
如下變數d是addressable的,可以利用d.Set(reflect.ValueOf(11))進行賦值。
也可以利用d.Addr().Interface().(*int)轉為指標再設定值,也可以利用d.SetInt(99)賦值:

func addressable_main() {    x := 2    d := reflect.ValueOf(&x).Elem()    fmt.Println(d.CanAddr())    d.Set(reflect.ValueOf(11))    fmt.Println(x)    dp := d.Addr().Interface().(*int)    *dp = 12    fmt.Println(x)    d.SetInt(99)    fmt.Println(x)}

如下:對於int類型的變數x,使用rx.SetString("hello")會引起panic。對於interface{}類型的變數y,既可以使用ry.Set(reflect.ValueOf(3)),也可以使用ry.Set(reflect.ValueOf("hello")),但是使用ry.SetInt(2)會引起panic.

func addressable_main2() {    x := 2    rx := reflect.ValueOf(&x).Elem()    rx.SetInt(2)    rx.Set(reflect.ValueOf(3))    // rx.SetString("hello")//pannic    var y interface{}    ry := reflect.ValueOf(&y).Elem()    ry.Set(reflect.ValueOf(3))    ry.Set(reflect.ValueOf("hello"))    fmt.Println(y)    // ry.SetInt(2) //panic}func addressable_main3() {    stdout := reflect.ValueOf(os.Stdout).Elem()    fmt.Println(stdout.Type())    fd := stdout.FieldByName("fd")    fmt.Println(fd.Int())}

擷取結構體方法的名稱

由下代碼可以看到v作為reflect.Value類型的變數
可以通過v.Method(i).Type().String()v.Type().Method(i).Name()

func PrintMethodName(x interface{}) {    v := reflect.ValueOf(x)    vt := v.Type()    fmt.Printf("type %s \n", vt)    for i := 0; i < v.NumMethod(); i++ {        methType := v.Method(i).Type()        fmt.Println("func (%s) :%s :%s\n", vt, vt.Method(i).Name,            strings.TrimPrefix(methType.String(), "func"))    }}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.