go语言 反射

2018-07-20  本文已影响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对象
}
上一篇下一篇

猜你喜欢

热点阅读