对接口类型变量取值
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))
}