在Go中,有没有办法比较两个没有嵌套switch语句的混合类型接口?

时间:2015-10-21 11:21:26

标签: go interface type-switch

Go interface{}类型是该语言最好也最烦人的功能,我发现。我正在尝试创建一个简单的用户可自定义的验证规则解决方案,用户可以在其中定义:

  • 比较运算符。
  • 比较操作数。
  • 导致要测试的值的地图键。

以及一个简单的布尔表达式解析器,它允许用户使用AND和OR组合多个规则。到目前为止一切运行良好,表达式可以成功解析,标记和评估,但是它会对给定数据运行导致问题的规则。

这是实际评估数据的函数的当前版本:

/*
validate returns a boolean value denoting whether a test was successful. This
function will panic if the type assertions fail.
*/
func (sfvre standardFieldValidationRuleEntry) validate(fieldValue interface{}) bool {

    switch sfvre.Operator() {
    case VROP_EQUAL:
        return fieldValue == sfvre.ComparisonOperand()
    case VROP_NEQUAL:
        return fieldValue != sfvre.ComparisonOperand()
    case VROP_GT:
        return fieldValue.(int) > sfvre.ComparisonOperand().(int)
    case VROP_LT:
        return fieldValue.(int) < sfvre.ComparisonOperand().(int)
    case VROP_GTET:
        return fieldValue.(int) >= sfvre.ComparisonOperand().(int)
    case VROP_LTET:
        return fieldValue.(int) <= sfvre.ComparisonOperand().(int)
    case VROP_CONTAINS:
        return strings.Contains(fieldValue.(string), sfvre.ComparisonOperand().(string))
    case VROP_NCONTAINS:
        return !strings.Contains(fieldValue.(string), sfvre.ComparisonOperand().(string))
    default:
        return false
    }
}

此时操作员暗示数据是否为数字(大于,小于等)。 int的类型断言在构建包的其他部分时完成了这项工作,但是完成的系统也应该能够使用float64并能够处理混合类型的比较。

我目前唯一可以看到的方法是使用多个嵌套类型开关,每个开关都有一个级别:

  • 操作员。
  • 给定的字段值的类型。
  • 比较操作数的类型。

但这有可能变得非常大而且不易管理。是否有一种“更清洁”的方式来做我看不到的,或者我是否坚持使用嵌套开关?

1 个答案:

答案 0 :(得分:0)

我现在获得的解决方案(感谢@Volker提供的建议)对需要比较的值进行快速类型切换,然后在Operator()开关中使用原件,它使用具体浮点值:

/*
validate returns a boolean value denoting whether a test was successful. This
function will panic if the type assertions fail.
*/
func (sfvre standardFieldValidationRuleEntry) validate(fieldValue interface{}) bool {

    var floatFieldVal, floatCompVal float64

    //If the interface is int or float, convert it to a statically typed float64.
    switch fieldValue.(type) {
    case int:
        floatFieldVal = float64(fieldValue.(int))
    case float64:
        floatFieldVal = fieldValue.(float64)
    }

    //Do the same with the comparison value.
    switch sfvre.ComparisonOperand().(type) {
    case int:
        floatCompVal = float64(sfvre.ComparisonOperand().(int))
    case float64:
        floatCompVal = sfvre.ComparisonOperand().(float64)
    }

    switch sfvre.Operator() {
    case VROP_EQUAL:
        return fieldValue == sfvre.ComparisonOperand()
    case VROP_NEQUAL:
        return fieldValue != sfvre.ComparisonOperand()
    case VROP_GT:
        return floatFieldVal > floatCompVal
    case VROP_LT:
        return floatFieldVal < floatCompVal
    case VROP_GTET:
        return floatFieldVal >= floatCompVal
    case VROP_LTET:
        return floatFieldVal <= floatCompVal
    case VROP_CONTAINS:
        return strings.Contains(fieldValue.(string), sfvre.ComparisonOperand().(string))
    case VROP_NCONTAINS:
        return !strings.Contains(fieldValue.(string), sfvre.ComparisonOperand().(string))
    default:
        return false
    }
}

它并不能捕捉到所有内容,但是根据用户可以根据他们进行比较的字段来限制用户可以选择的操作员可以减轻这种影响,但这个更大的解决方案的一部分在这里是无关紧要的。< / p>

相关问题