我们知道,go语言是一门强类型的语言,我们在某些时候可能需要再同一个api接口中接收和处理不同类型的参数, 这时我们就可以通过定义一个 any类型的请求参数来让gin框架帮我们接收和解析不同类型的请求参数。
下面我们就以接收任意类型的ids数据为例来演示gin框架中任意类型的请求参数接收和解析的方法
请求参数接收结构体定义
// 定义一个结构体,用来接收任意类型的id数据
type AnyIdsReq struct {
Ids any `form:"ids"` // 这里的tag form:"ids" 是gin框架中用来接收表单名为ids的数据的
}
gin框架接收和解析任意类型 any / interface{} 参数示例
下面示例演示了gin框架里面接收任意类型的参数并转换为 []int64类型的示例,如果需要其他的类型,可以参考下面的模式, 进行相应的数据转换即可。 记着应用go语言里面类型转换的3大法宝即可,即:反射, 类型断言.(T) 和 .(type) 类型获取
func (a *parserApi) CheckUrl(c *ginx.XContext) {
var req = &AnyIdsReq{}
// 获取参数
if err := c.ShouldBind(req); err != nil {
// gin 参数绑定异常了。。。。。
return
}
// 定义一个我们需要的数据类型变量
idss := make([]int64, 0)
// 通过反射获取反射类型
rt:=reflect.TypeOf(req.Ids)
// 根据不同的类型来解析数据,
switch rt.Kind() {
case reflect.Float64: // 这里注意int类型的数据json后会变成float64
idss = append(idss, ToInt64(req.Ids))
case reflect.Slice: // 数据是切片类型
if iss,ok:=req.Ids.([]interface{});ok {
for _, v := range iss {
idss = append(idss, ToInt64(v))
}
}
// 还需要处理其他的类型? 这里接着case 然后接着处理即可
}
// 到这里我们就将前端传递的参数,不管是当个值还是数组,这里都统一转换成了我们指定类型的数组 idss
// ...... 其他逻辑
}
注意,gin框架请求参数的绑定和解析底层使用了json, 所以前端发送的int类型数据 会被转换为 float64类型, 我们在接收和处理any类型的数据的时候需要注意这点。
ToInt64 转换任意any/interface{}类型数据到int64类型
// ToInt64 转换任意any/interface{}类型数据到int64类型
func ToInt64(val interface{}) int64 {
if val == nil {
return 0
}
// .(type) 这个是一个固定用法,目的就是获取go语言的类型表示
switch value := val.(type) {
case int:
return int64(value)
case int8:
return int64(value)
case int16:
return int64(value)
case int32:
return int64(value)
case int64:
return value
case uint:
return int64(value)
case uint8:
return int64(value)
case uint16:
return int64(value)
case uint32:
return int64(value)
case uint64:
return int64(value)
case float32:
return int64(value)
case float64:
return int64(value)
case bool:
if value {
return 1
}
return 0
case string:
// 将value.(string)断言为字符串后解析为int64
if v, err := strconv.ParseInt(value.(string), 16, 64); err == nil {
return v
}else{
return 0
}
default:
// 其他情况返回0 也可以自己处理
return 0
}
}
总结:
接收任意类型的参数的核心就是数据类型的转换,这里应用了go语言里面数据类型转换的3大法宝,反射,类型断言和类型获取。