基本介绍
返回v持有值的方法集的方法数目。
- func (v Value) NumField() int
返回v持有的结构体类型值的字段数,如果v的Kind不是Struct会panic
Call方法使用输入的参数in调用v持有的函数。例如,如果len(in) == 3,v.Call(in)代表调用v(in[0], in[1], in[2])(其中Value值表示其持有值)。如果v的Kind不是Func会panic。它返回函数所有输出结果的Value封装的切片。和go代码一样,每一个输入实参的持有值都必须可以直接赋值给函数对应输入参数的类型。如果v持有值是可变参数函数,Call方法会自行创建一个代表可变参数的切片,将对应可变参数的值都拷贝到里面。
结构体类型反射代码
// 结构体 反射 案例
// 反射可以用来开发底层框架
package main
import (
"fmt"
"reflect"
)
// 这就需要通过 tag 来转化大写的字段,同时又保证内部调用的时候可以暴露变量
// 反射原理
type People struct {
Name string `json:"name01"`
Age int `json:"age"`
Height float64 `json:"height"`
Action string
}
// 给结构体绑定方法
func (p People) Print() {
fmt.Println("print() = ", p)
}
func (p People) GetSum(n1, n2 int) int {
return n1 + n2
}
func (p People) Set(name string, age int, height float64, action string) {
p.Name = name
p.Age = age
p.Height = height
p.Action = action
}
func TestStruct(a interface{}) {
typ := reflect.TypeOf(a)
val := reflect.ValueOf(a)
kd := val.Kind()
if kd != reflect.Struct {
fmt.Println("except struct, but its not")
return
}
// 结构体字段
num := val.NumField()
fmt.Printf("struct has %v fields \n", num)
for i := 0; i < num; i++ {
fmt.Printf("第%v个字段:%v \n", i+1, val.Field(i))
tagVal := typ.Field(i).Tag.Get("json")
if tagVal != "" {
fmt.Printf("第%v个字段, tag : %v \n", i+1, tagVal)
}
}
// 结构体方法
numOfMethod := val.NumMethod()
fmt.Printf("struct 有 %v 个方法 \n", numOfMethod)
val.Method(1).Call(nil)
var params []reflect.Value
params = append(params, reflect.ValueOf(10))
params = append(params, reflect.ValueOf(40))
res := val.Method(0).Call(params)
fmt.Println("res = ", res[0].Int())
}
func main() {
// struct
p1 := People{
Name: "tom",
Age: 18,
Height: 178.5,
Action: "衣食住行",
}
TestStruct(p1)
}