go中反射的基本使用

对接口类型变量取值

m := make(map[string]interface{})
m["session_id"] = "ssffsdfdfs"
m["people"] = map[string]interface{}{"name":"zhangsan","age":18}
fmt.Print(m["peolpe"]["name"])

上面代码打印时会报错,这是因为people对应的是接口类型的值,不能使用map取值的方式取值
需要先把people转换为map类型,如下

m2 := m["people"].(map[string]interface{})
fmt.Print(m2["name"])

修改后可以顺利执行,然后我们追加如下代码

var young float64 = 16
if m2["age"] > young {
	fmt.Print("is old")
}

再次报错
这是因为age对应的值,仍然是接口类型。接口类型的值,不能直接与其他变量比较。
我们除了可以使用断言,修改age的类型。也可以通过反射,修改值的类型

if reflect.ValueOf(m2["age"]).Float() > young{
	fmt.Print("is old")
}

自定义CallUserFuncArray方法

go没有类似php中call_user_func_array()的方法,但我们可以通过反射的call方法自定义一个类似的方法,具体代码如下

// obj 实现了要回调的方法的变量
// name 要回调的方法名称
// obj 要传入回调方法的变量切片
func callUserFuncArray(obj interface{},name string,param []interface{}) (interface{},error) {
	t := reflect.TypeOf(obj)
	_func,ok := t.MethodByName(name)
	if !ok{
		return nil,errors.New("方法不存在")
	}
	_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,nil
}

具体使用场景,可以查看go中指针的操作规则中的使用案例
此处我们只针对调用该方法后,如何使用返回值进行说明

		res,resErr := callUserFuncArray(rows,"Exec",paramsSlice)
		checkErr(resErr)
		//callUserFuncArray方法返回的res是接口类型的值,需要使用断言,把返回值还原为原类型
		//查看reflect包的源码后,我们知道call方法返回值是reflect.Value类型的切片
		resSlice := res.([]reflect.Value)
		//resSlice 中保存的是回调方法返回的值,但是被call转换成了Value类型
		//根据回调方法中error返回值的位置,调取error在切片resSlice 相应的键值,来判断方法执行状态
		if(resSlice[1].Interface() == nil){
			//Value类型的的变量,可通过方法Interface()方法获取原始数据的接口形式,再配合断言可转换为原值
			res := resSlice[0].Interface().(sql.Result)
			num := res.LastInsertId()
		}else{
			//错误信息不为nil,使用断言获取具体的error错误信息
			panic(resSlice[1].Interface().(error))
		}
		
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值