赞
踩
我们来看一个相互转换的例子,这在反射中是很常用的
var student Student
var num nt
func trans(b interface{}) {
// 将b这个interface{}类型转为reflect.Value类型
rVal := reflect.ValueOf(b)
// 将reflect.Value类型转为interface{}类型
iVal := rVal.Interface()
// 将interface类型转为原来的变量类型--类型断言
val := iVal.(Student)
// 若b是int类型,还可以直接用reflect.Value类型里面的Int方法取变量值,之后才能和其他int类型进行操作
n := rVal.Int()
}
func main() {
var num int = 10
// 这里需要传地址
rVal = reflect.ValueOf(&num)
// 这里不能直接set,需要用指针指向的elem来修改
rVal.Elem().SetInt(20)
}
package main
import(
"fmt"
"reflect"
)
type Monster struct {
Name string `json:name`
Age int `json:monster_age`
Score float32
Sex string
}
func (s Monster)Print() {
fmt.Println("print monster", s)
}
func (s Monster)GetSum(n1, n2 int) int {
return n1 + n2
}
func (s Monster) Set(Name string, Age int, Score float32, Sex string) {
s.Name = Name
s.Age = Age
s.Score = Score
s.Sex = Sex
}
func TestStruct(b interface{}) {
rtype := reflect.TypeOf(b)
rVal := reflect.ValueOf(b)
kd := rVal.Kind()
if kd != reflect.Struct {
fmt.Println("expect struct")
return
}
// 获取该结构体有几个字段
num := rVal.NumField()
fmt.Printf("struct has %d filed", num)
for i :=0; i < num; i++ {
// 通过Field方法遍历字段,注意这里Field(i)是reflect.Value类型,不能直接用于运算,也需要进行类型断言才能运算
fmt.Printf("field %d value is %v", i, rVal.Field(i))
// 这里不能用value获取tag,只能用reflect.Type来获取标签,如果结构体不止一个标签,那么这里只能获取json的标签数据
tagval := rtype.Field(i).Tag.Get("json")
if tagval != "" {
fmt.Printf("field %d tag is:%v", i, tagval)
}
}
//获取到该结构体有多少个方法,方法序号从0开始,方法的排序默认按照函数名的ascii码大小比较排序
numOfMethod := val.NumMethod()
fmt.Printf("struct has %d methods\n", numOfMethod)
// var params []reflect.Value
// 调用第二个方法:Print方法
rval.Method(1).Call(nil)
// 调用结构体的第1个方法Method(0)
var params []reflect.Value
params append(params, reflect.Valueof(10))
params append(params, reflect.Valueof(40))
// Call方法参数类型reflect.Value类型的切片类型,因此上面先构造切片,返回值也是一个切片
res := rval.Method(0).Call(params)//传入的参数是[]reflect.Value
fmt.Println("res=",res[0].Int())//返回结果,返回的结果是[]reflect.Value*/
}
func main() {
var m1 Monster := Monster{
Name : "huangshulang",
Age : 400,
Score : 30.9,
}
// 将Monster实例传给TestStruct函数即可调用结构体相关的方法,这在一些固定框架的代码中很有用,我们通常只需要定义好结构体及对应的方法,框架里面通过反射即可相关功能自动处理,无需显式通过结构体实例调用
TestStruct(m1)
}
补充上面Call方法的官方说明:
这个基本上与上面一致,需要注意的市,我们在传参的时候,TestStruct(&m1)要传地址,才能修改成功,其余的就是用类似
rval.Elem().Field(0).SetString(“白象精”)修改方法来操作修改即可
定义了两个函数test1和test2,定义一个适配器函数用作统一处理接口
(1)定义了两个函数
test1 := func(v1 int, v2 int){
t.Log(v1,v2)
}
test2 := func(v1 int, v2 int, s string){
t.Log(v1,v2,s)
}
现在要定义一个适配器函数用作统一处理接口,其大致结构如下
bridge:=func(call interface{}, args.….interface{}){
// 内容
}
实现调用test1对应的函数
bridge(test1, 1, 2)
实现调用test2对应的函数
bridge(test2, 1, 2, “test2”)
func TestReflectFunc(t *testing.T){
call1 := func(v1 int,v2 int){
t.Log(v1,v2)
}
call2 := func(v1 int,v2 int,s string){
t.Log(v1,v2,s)
}
var(
function reflect.Value
inValue []reflect.Value
n int
)
bridge := func(call interface{}, args...interface{}){
n = len(args)
inValue=make(reflect.Value, n)
for i := 0; i<n; i++ {
inValue[i]=reflect.ValueOf(args[i])
}
function reflect.ValueOf(call)
function.Call(inValue)
}
bridge(call1,1,2)
bridge(call2,1,2,"test2")
type user struct {
Userld string
Name string
}
func TestReflectStruct(t *testing.T) {
var (
model *user
sv reflect.Value
)
// model指向一个user对象
model = &user{}
// 将model转成一个reflect.Value类型
sv = reflect.ValueOf(model)
t.Log("reflect.ValueOf",sv.Kind().String())
// 这里获取Elem之后,sv实际就指向user对象了,后续就能直接用sv来操作结构体了
sv = sv.Elem()
t.Log("reflect.ValueOf.Elem",sv.Kind().String())
sv.FieldByName("Userld").SetString("12345678")
sv.FieldByName("Name").SetString("nickname")
t.Log("model",model)
}
package test
import (
"testing"
"reflect"
)
type user struct {
Userld string
Name string
}
func TestReflectStructPtr(t *testing.T) {
var(
model *user
st reflect.Type
elem reflect.Value
)
st = reflect.Typeof(model)/获取类型*user
t.Log("reflect.Typeof",st.Kind().String())//ptr
st = st.Elem()/st指向的类型
t.Log("reflect.TypeOf.Elem",st.Kind).String())//struct
elem = reflect.New(st)/New返回一个Value类型值,该值持有一个指向类型为type的新申请的零值的指针
t.Log("reflect.New",elem.Kind().String())//ptr
t.Log("reflect.New.Elem",elem.Elem().Kind().StringO)//struct
/model就是创建的user结构体变量(实例)
model = elem.Interface().(*user)/model:是user它的指向和elem是一样的
elem = elem.Elem()/取得elem指向的值
elem.FieldByName("Userld").SetString("12345678")/赋值.
elem.FieldByName("Name").SetString("nickname")
t.Log("modelmodel.Name", model ,model.Name)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。