-2

语境:

在 Echo 框架中使用自定义的 Binder 和 Validator。活页夹使用 的签名(interface{}, echo.Context),但指针始终由 传递和检查echo.DefaultBinder

当由于某种未知原因传递数组时,由于某种原因,我无法验证结构数组。因此,我试图验证接口中的每个元素,如果此接口是数组或切片。

问题:

我找不到一种方法来将interfacea 转换为 avalue而不是 apointer并遍历该数组的值以验证它们中的每一个。

到目前为止我的代码:

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
}
4

1 回答 1

1

我宁愿使用类型断言而不是反射,因为反射在性能方面很慢并且使用起来不友好。
为了说明我的意思,请查看此示例代码,其中我有一个接受类型参数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 值:value1
索引:1 值:value2
键:key1 值:value1
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
}
于 2021-05-10T19:45:25.600 回答