package main
import (
"fmt"
"go/ast"
"reflect"
)
type Member struct {
Id int `json:"id" orm:"member_id"`
Name string `json:"name"`
status bool
}
func (m *Member) SetStatus(s bool) {
m.status = s
}
func (m *Member) GetStatus() bool {
return m.status
}
func (m Member) String() string {
return fmt.Sprintf("id: %d, name: %s", m.Id, m.Name)
}
// 如果是值传递那么反射获取的对象将不能修改此值,否则 panic
func Parse(v interface{}) {
// 获取 v 的变量值,如果是地址传递获取的是指针,值传递则为变量值
rValue := reflect.ValueOf(v)
// 判断是否为一个指针,如果是指针就通过 Elem() 获取指针指向的变量值
rValue = reflect.Indirect(rValue)
// 获取 v 的变量类型
rType := rValue.Type()
// rType := reflect.TypeOf(v)
switch rType.Kind() {
case reflect.Struct:
// 遍历结构体字段
for i := 0; i < rValue.NumField(); i++ {
field := rType.Field(i)
// 忽略匿名字段和私有字段
if !field.Anonymous && ast.IsExported(field.Name) {
// 获取结构体字段的 interface{} 变量
fmt.Println(rValue.Field(i).Interface())
// 对于值传递的结构体使用 Addr() 获取结构体字段 *interface{} 变量会报错
fmt.Println(reflect.TypeOf(rValue.Field(i).Addr().Interface()))
// 获取字段 tag
fmt.Println(rType.Field(i).Tag.Get("json"))
}
}
// 根据字段名获取字段 interface{}
fmt.Println(rValue.FieldByName("Name").Interface())
// 获取非指针方法数量,案例中的 Member 的 String 方法
fmt.Println(rValue.NumMethod())
// 获取所有方法数量
fmt.Println(rValue.Addr().NumMethod())
// 遍历结构体方法
rValue.Addr().MethodByName("SetStatus").Call([]reflect.Value{reflect.ValueOf(true)})
fmt.Println(rValue.Addr().MethodByName("GetStatus").Call(nil))
// 排序默认是按照函数名的排序(ASCII 码)
fmt.Println(rValue.Addr().Method(2).Call(nil))
fmt.Println(rValue.Method(0).Call(nil))
// 创建一个新反射对象
fmt.Println(reflect.New(rType).Elem().FieldByName("Id"))
case reflect.Func:
num := 2
argv := make([]reflect.Value, rType.NumIn())
for i := range argv {
if rType.In(i).Kind() == reflect.Int {
argv[i] = reflect.ValueOf(num)
}
}
result := rValue.Call(argv)
if len(result) == 1 {
fmt.Println(result[0].Int())
}
case reflect.Int:
// 修改值
rValue.SetInt(127)
// 从反射对象获取 interface{} 变量
rIntf := rValue.Interface()
// 根据 interface{} 进行类型断言
if num, ok := rIntf.(*int); ok {
fmt.Println(num)
}
case reflect.Slice:
// 切片类型
fmt.Println(rType.Kind())
// 切片内元素类型
// Elem() 作用是返回接口 v 包含的值或 v 指向的指针
fmt.Println(rType.Elem().Kind())
}
}
func Add(a, b int) int {
return a + b
}
func main() {
m := &Member{
Id: 23,
Name: "jack",
}
Parse(m)
fmt.Println(m.GetStatus())
// 函数调用
Parse(Add)
num := 6
// 如果为值传递修改时会 panic
Parse(&num)
fmt.Println(num)
var ms []Member
Parse(&ms)
}
/*
23
*int
id
jack
*string
name
jack
1
3
[<bool Value>]
[id: 23, name: jack]
[id: 23, name: jack]
0
true
4
127
slice
struct
*/
来源:oschina
链接:https://my.oschina.net/lanseyujie/blog/4328158