golang 通过反射机制实现类似php call_user_func_array函数

# golang / 269访问 / 0评论 / 2021-09-08

完整代码

package main

import (
	"fmt"
	"reflect"
)

type Validate struct {

}

func (v *Validate)Is(name string,data string) string{
	fmt.Println(name)
	fmt.Println(data)
	return "调用成功"
}

func call_user_func_array(obj interface{},name string,param []interface{}) (interface{},bool) {
	t := reflect.TypeOf(obj)
	_func,ok := t.MethodByName(name)
	if !ok{
		fmt.Println("方法不存在")
		return nil,false
	}
	_param := make([]reflect.Value,len(param)+1)
	_param[0] =  reflect.ValueOf(obj)
	for key,value := range param{
		_param[key+1] =  reflect.ValueOf(value)
	}
	res := _func.Func.Call(_param)
	return res,false
}

func main(){
	_func := "Is"
	param := []interface{}{
		"张三","李四",
	}
	v := &Validate{}
	res,_:= call_user_func_array(v,_func,param)
	fmt.Println(res)
}

运行结果

张三
李四
[调用成功]

代码解析

func call_user_func_array(obj interface{},name string,param []interface{}) (interface{},bool) {
	t := reflect.TypeOf(obj)
	//TypeOf下的MethodByName方法有两个返回值(Method, bool),可以先通过bool值来判断该方法是否存在
	_func,ok := t.MethodByName(name)
	if !ok{
		fmt.Println("方法不存在")
		return nil,false
	}
	//这里对调用方法的参数进行处理
	//这里的参数必须使用[]reflect.Value
	//这里我为什么要对切片的长度进行加1呢?
	//在方法 func (v *Validate)Is(name string,data string)中这里算的参数是3个,v *Validate 也算一个参数
	//如果不进行+1 会抛出reflect: Call with too few input arguments 错误
	_param := make([]reflect.Value,len(param)+1)
	_param[0] =  reflect.ValueOf(obj)
	for key,value := range param{
		_param[key+1] =  reflect.ValueOf(value)
	}
	res := _func.Func.Call(_param)
	return res,false
}

最近正好需要使用到这么一个方法,这里主要来做一个记录,防止忘了

5

本文地址: https://www.kumaomao.cn/article/XETLDBYWPG.html