上下文:
在Echo Framework中使用自定义绑定器和验证器。绑定器使用(interface{}, echo.Context)
的签名,但指针总是由echo.DefaultBinder
传递和检查。
由于某种原因,当一个数组由于某种未知原因被传递时,我在验证结构的数组时遇到了问题。因此,如果接口是Array或Slice,我将尝试验证接口中的每个元素。
问题:
我找不到既将interface
强制转换为value
而不是pointer
,又遍历该数组的值以验证每个值的方法。
到目前为止我的代码:
func (cb *CustomBinder) Bind(i interface{}, c echo.Context) error {
db := new(echo.DefaultBinder)
validate := validator.New()
if err := db.Bind(i, c); err != nil {
return err
}
kind := reflect.ValueOf(i).Elem().Kind()
if kind == reflect.Array || kind == reflect.Slice {
// ... Iteration and Validation
} else {
if err := validate.Struct(i); err != nil {
return err
}
}
return nil
}
我宁愿使用类型断言而不是反射,因为反射在性能方面很慢,而且使用起来不友好
为了说明我的意思,请查看此示例代码,其中我有一个函数,它接受类型为interface{}
的参数,并根据数据类型打印值
package main
import (
"fmt"
)
func main() {
var dynamicValue interface{}
dynamicValue = []interface{}{"value1", "value2"}
printValue(dynamicValue)
dynamicValue = map[string]interface{}{"key1": "value1"}
printValue(dynamicValue)
dynamicValue = "value1"
printValue(dynamicValue)
}
func printValue(i interface{}) {
if arrayValue, isArray := i.([]interface{}); isArray {
for index, value := range arrayValue {
fmt.Printf("Index: %d Value: %v n", index, value)
}
} else if mapValue, isMap := i.(map[string]interface{}); isMap {
for key, value := range mapValue {
fmt.Printf("Key: %s Value: %v n", key, value)
}
} else if stringValue, isString := i.(string); isString {
fmt.Println(stringValue)
} else {
fmt.Println("Invalid data type! Only supports string, arrays and maps ")
}
}
输出:
索引:0值:值1
指数:1值:值2
键:键1值:值1
value1
游乐场:https://play.golang.org/p/TMfojVdoi5b
您可以在代码中使用这种类型断言逻辑来检查interface
是否是切片,并对其进行迭代以进行验证
像这样的东西,
func (cb *CustomBinder) Bind(i interface{}, c echo.Context) error {
db := new(echo.DefaultBinder)
validate := validator.New()
if err := db.Bind(i, c); err != nil {
return err
}
if arrayValue, isArray := i.([]interface{}); isArray {
// Iteration
for index, value := range arrayValue {
// Validation
}
} else {
if err := validate.Struct(i); err != nil {
return err
}
}
return nil
}