• [go 反射] 函数


    [go 反射] 函数

    go 函数反射的基础认识

    • 输入参数
    • 返回输出

    输入参数和输出

    NumIn()此方法属于reflect.Type接口,用于获取参数数量;In(int)用于获取对应位置的参数
    NumOut()此方法属于reflect.Type接口,用于获取返回变量的数量;Out(int)用于获取对应位置的返回变量

    演示

    var one func(string,int,bool)int
    
    tp:=reflect.TypeOf(one)
    fmt.Println(tp.NumIn(),tp.NumOut())
    //从左到右依次输出输入参数的变量基础类型
    for i:=0;i<tp.NumIn();i++{
        fmt.Println(tp.In(i).Kind())
    }
    //依次输出返回变量的基础类型
    for i:=0;i<tp.NumOut();i++{
        fmt.Println(tp.Out(i).Kind())
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    反射运行函数

    Call([]reflect.Value)[]relfect.Value属于reflect.Value结构体的方法,运行此方法即可达到调用函数的目的,参数通过反射过后放入数组内给call

    演示

    func Greet(name string)string{
        fmt.Println("call greet function")
        return "hello "+name
    }
    func main(){
        tp:=reflect.TypeOf(Greet)
        vl:=reflect.ValueOf(Greet)
        input:="jim"
        fmt.Println(tp.NumIn(),tp.NumOut())//两者都是1
        ans:=vl.Call([]reflect.Value{reflect.ValueOf(input)})
        reflect.ValueOf(&input).Elem().Set(ans[0])//将结果替换掉原来的input
        fmt.Println(input)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    终极实现——任意函数调用接口

    //能够通过此方法调用任意现存函数,并返回到结构体
    func AnyFunc[T any](src any, dst *T, args ...any) (err error) {
    	stp, dtp := reflect.TypeOf(src), reflect.TypeOf(dst).Elem()
    	svl, dvl := reflect.ValueOf(src), reflect.ValueOf(dst).Elem()
    	if svl.IsNil() || stp.Kind() != reflect.Func {
    		err = str_error("src function invaild")
    		return
    	}
    	if stp.NumIn() != len(args) {
    		err = str_error("args can't match the function args")
    		return
    	}
    	var argsvl []reflect.Value = make([]reflect.Value, len(args))
    	for i, ele := range args {
    		argsvl[i] = reflect.ValueOf(ele)
    	}
    	outvl := svl.Call(argsvl)
    	outcount := stp.NumOut()
    	if dst == nil && outcount > 0 {
    		err = str_error("dst is null")
    		return
    	}
    	if outcount == 1 {
    		if dtp == outvl[0].Type() {
    			if dvl.CanSet() {
    				dvl.Set(outvl[0])
    			} else {
    				err = str_error("dst can't be set")
    			}
    		} else {
    			err = str_error("dst type is don't match")
    		}
    	} else if outcount > 1 {
    		if dtp.Kind() == reflect.Struct {//结构体非严格匹配赋值,请看[go 反射] 结构体
    			if dtp.NumField() >= outcount {
    				var i, j = 0, 0
    				var anspos []int = make([]int, 0, outcount)
    				for i < dtp.NumField() && j < outcount {
    					if dtp.Field(i).Type == outvl[j].Type() {
    						if dvl.Field(i).CanSet() {
    							anspos = append(anspos, i)
    						}
    						j++
    					}
    					i++
    				}
    				if len(anspos) == outcount {
    					for key, pos := range anspos {
    						dvl.Field(pos).Set(outvl[key])
    					}
    				} else {
    					err = str_error("precheck failed")
    				}
    			} else {
    				err = str_error("your recieve struct fields not enough")
    			}
    		} else if dtp.Kind() == reflect.Map {
    			if dvl.IsNil() {
    				dvl.Set(reflect.MakeMap(dtp))
    			}
    		} else {
    			err = str_error("you should use struct pointer to recieve return ans")
    		}
    	}
    	return
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
  • 相关阅读:
    怎样能写好年终总结报告?
    SAP-QM-检验批和物料凭证
    多线程七夕特别版(二)互斥锁-死锁-等待通知机制
    springbootMysql文华学院青年志愿者服务预约系统97973-计算机毕业设计项目选题推荐(附源码)
    开源大数据集群部署(十四)Ranger集成Hbase
    React源码分析4-深度理解diff算法
    转置卷积理论解释(输入输出大小分析)
    【frida】HLL 登录流程分析 找关键 Call
    第三章:运算符
    Linux常用命令——系统痕迹命令
  • 原文地址:https://blog.csdn.net/A_super_C/article/details/134198991