判断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"))
}
}
有疑问加站长微信联系(非本文作者)