结构体中使用反射
一、Field
v.NumField():获取结构体字段数量
v.Field(i):获取第i个字段的值,角标从0开始
示例代码:
package main
import (
"reflect"
"fmt"
)
type Student1 struct {
Id int
Name string
Age int
Cls string
}
func main() {
student := Student1{
Id:1,
Name:"张三",
Age:18,
Cls:"高三2班",
}
v := reflect.ValueOf(student)
fmt.Println(v)
t := reflect.TypeOf(student)
fmt.Println(t)
fmt.Println(t.Kind())
// 判断类型
switch t.Kind() {
case reflect.Struct:
fmt.Println("student是结构体")
}
fmt.Println(v.NumField()) // 获取结构体属性字段数量
fmt.Println(v.Field(0)) // 获取结构体中字段对应角标的值
fmt.Println(v.Field(1))
for i:=0;i< v.NumField();i++ { // 也可以使用循环获取所有的
fmt.Println(t.Field(i).Name) // 打印字段名称,注意是type中的
fmt.Println(v.Field(i)) // 打印字段对应的值,注意是value中的
}
// 修改值
v2 := reflect.ValueOf(&student)
v2.Elem().Field(0).SetInt(2) // 一定要是对应类型的
}
注意:如果结构体字段不是首字母大写,则不能反射出私有变量
二、Method
t.NumMethod():获取方法数量
t.Method(i):获取角标为i的方法
示例代码:
package main
import (
"reflect"
"fmt"
)
type Student1 struct {
Id int
Name string
Age int
Cls string
}
func (s *Student1) Eat() {
fmt.Println("吃饭")
}
func main() {
student := Student1{
Id:1,
Name:"张三",
Age:18,
Cls:"高三2班",
}
// v := reflect.ValueOf(student)
t := reflect.TypeOf(&student) // 或者v.Type也可以,必须是指针
fmt.Println(t.NumMethod())
fmt.Println(t.Method(0))
fmt.Printf("%T\n",t.Method(0)) // reflect.Method
}
三、字符串方法反射调用
package main
import (
"reflect"
"fmt"
)
type Student1 struct {
Id int
Name string
Age int
Cls string
}
func (s *Student1) Eat() {
fmt.Println("吃饭")
}
func (s *Student1) Run() {
fmt.Println("跑")
}
func main() {
student := Student1{
Id:1,
Name:"张三",
Age:18,
Cls:"高三2班",
}
v := reflect.ValueOf(&student) // 这里必须是指针
v2,_ := v.MethodByName("Eat") // 必须有这个方法,否则会报错:panic: reflect: call of reflect.Value.Call on zero Value
v2.Call([]reflect.Value{}) // call的参数是数组,类型是reflect.Value
v3 := v.MethodByName("Run")
v3.Call([]reflect.Value{})
}
panic: reflect: call of reflect.Value.Call on zero Value
1.没有使用指针
2.没有这个方法
四、获取结构体里tag的信息
t := reflect.TypeOf(&student)
field0 := t.Elem().Field(0)
fmt.Printf("tag json=%s\n", field0.Tag.Get("json"))