美文网首页
go语言 反射

go语言 反射

作者: 我就是小政政 | 来源:发表于2018-07-20 12:43 被阅读0次
    为何需要反射?

    下面例子试图打印出传入的interface值,无法找到无尽的未知类型的表示方式,我们被卡住了。这就是我们为何需要反射的原因。

    func Sprint(x interface{}) string {
        type stringer interface {
            String() string
        }
        switch x := x.(type) {
        case stringer:
            return x.String()
        case string:
            return x
        case int:
            return strconv.Itoa(x)
        // ...similar cases for int16, uint32, and so on...
        case bool:
            if x {
                return "true"
            }
            return "false"
        default:
            // array, chan, func, map, pointer, slice, struct
            return "???"
        }
    }
    
    reflect.Type与reflect.Value
    reflect.Type //表示一个go类型
    reflect.Value //表示一个任意类型的值
    

    函数 reflect.TypeOf 接受任意的 interface{} 类型,并以 reflect.Type 形式返回其动态类型:

    t := reflect.TypeOf(3)  // a reflect.Type
    fmt.Println(t.String()) // "int"
    fmt.Println(t)          // "int"
    

    因为 reflect.TypeOf 返回的是一个动态类型的接口值,它总是返回具体的类型。

    var w io.Writer = os.Stdout
    fmt.Println(reflect.TypeOf(w)) // "*os.File"
    

    函数 reflect.ValueOf 接受任意的 interface{} 类型,并返回一个装载着其动态值的 reflect.Value

    v := reflect.ValueOf(3) // a reflect.Value
    fmt.Println(v)          // "3"
    fmt.Printf("%v\n", v)   // "3"
    fmt.Println(v.String()) // NOTE: "<int Value>"
    

    对 Value 调用 Type 方法将返回具体类型所对应的 reflect.Type:

    t := v.Type()           // a reflect.Type
    fmt.Println(t.String()) // "int"
    

    reflect.ValueOf 的逆操作是 reflect.Value.Interface 方法。它返回一个 interface{} 类型,装载着与 reflect.Value 相同的具体值:

    v := reflect.ValueOf(3) // a reflect.Value.  v:3
    x := v.Interface()      // an interface{}. x:3
    i := x.(int)            // an int. I:3
    fmt.Printf("%d\n", i)   // "3"
    

    我们使用 reflect.Value 的 Kind 方法来替代之前的类型 switch。虽然还是有无穷多的类型,但是它们的 kinds 类型却是有限的:Bool、String 和 所有数字类型的基础类型;Array 和 Struct 对应的聚合类型;Chan、Func、Ptr、Slice 和 Map 对应的引用类型;interface 类型;还有表示空值的 Invalid 类型。(空的 reflect.Value 的 kind 即为 Invalid。)

    package format
    
    import (
        "reflect"
        "strconv"
    )
    
    // Any formats any value as a string.
    func Any(value interface{}) string {
        return formatAtom(reflect.ValueOf(value))
    }
    
    // formatAtom formats a value without inspecting its internal structure.
    func formatAtom(v reflect.Value) string {
        switch v.Kind() {
        case reflect.Invalid:
            return "invalid"
        case reflect.Int, reflect.Int8, reflect.Int16,
            reflect.Int32, reflect.Int64:
            return strconv.FormatInt(v.Int(), 10)
        case reflect.Uint, reflect.Uint8, reflect.Uint16,
            reflect.Uint32, reflect.Uint64, reflect.Uintptr:
            return strconv.FormatUint(v.Uint(), 10)
        // ...floating-point and complex cases omitted for brevity...
        case reflect.Bool:
            return strconv.FormatBool(v.Bool())
        case reflect.String:
            return strconv.Quote(v.String())
        case reflect.Chan, reflect.Func, reflect.Ptr, reflect.Slice, reflect.Map:
            return v.Type().String() + " 0x" +
                strconv.FormatUint(uint64(v.Pointer()), 16)
        default: // reflect.Array, reflect.Struct, reflect.Interface
            return v.Type().String() + " value"
        }
    }
    
    

    reflect.Value 的 FieldByName方法

    type Foo struct {
    ⇥   X string
    ⇥   Y int
    }
    
    func main() {
    
    ⇥   var foo = Foo{"abc", 123}
    
    ⇥   val := reflect.ValueOf(foo)
    ⇥   fmt.Println(val.FieldByName("a")) //<invalid reflect.Value>
    ⇥   //fmt.Println(val.FieldByName("a").Interface()) //报错
    ⇥   fmt.Println("==?", val.FieldByName("a") == reflect.ValueOf(nil))
    ⇥   fmt.Println("==?", val.FieldByName("a").Kind() == reflect.Invalid)
    
    ⇥   typ := reflect.TypeOf(foo)
    ⇥   fmt.Println(typ.FieldByName("a")) //{  <nil>  0 [] false} false StructField对象
    }
    

    相关文章

      网友评论

          本文标题:go语言 反射

          本文链接:https://www.haomeiwen.com/subject/qnhopftx.html