为何需要反射?
下面例子试图打印出传入的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对象
}
网友评论