为了账号安全,请及时绑定邮箱和手机立即绑定

是否可以从字符串创建比较运算符?

是否可以从字符串创建比较运算符?

Go
隔江千里 2023-08-07 18:53:54
我正在尝试创建一个函数,该函数将从预定义的数组中生成 if 条件。例如:package errorstype errorCase struct {    // This is the field I need to get in another struct    Field        string    // The comparison operator    TestOperator string    // The value that the expected one should not with equal...    WrongValue   interface{}}var ErrorCases = []*errorCase{ {    "MinValue",    "<",    0,}, {    "MaxValue",    "==",    0,}}实际上,我用 for 循环创建了一个新函数,该函数迭代所有这些“错误情况”func isDirty(questionInterface models.QuestionInterface) bool {    for _, errorCase := range errors.ErrorCases {        s := reflect.ValueOf(&questionInterface).Elem()        value := s.Elem().FieldByName(errorCase.Field)        // At this point I need to create my if condition        // to compare the value of the value var and the wrong one        // With the given comparison operator    }    // Should return the comparison test value    return true}是否可以创建这样的 if 条件?使用反射包?我认为这是可能的,但我不知道应该从哪里开始。
查看完整描述

1 回答

?
jeck猫

TA贡献1909条经验 获得超7个赞

这个有可能。我以前构建过一个像这样的通用比较库。

简单来说,比较包含三个部分:

  1. 某种值,位于比较的左侧

  2. 运算=<>, ...)。

  3. 某种值,位于比较的右侧

这 3 个部分仅包含两种不同的类型 - valueoperator。我试图将这两种类型抽象为它们的基本形式。

  • value可以是任何东西,所以我们使用空接口 - interface{}

  • 运算符是有限集的一部分,每个运算符都有自己的规则。

type Operator int
const (
    Equals Operator = 1
    )

评估与符号的比较=只有一条有效规则 - 两个值应该属于同一类型。你无法比较1hello。之后,您只需确保这些值相同即可。

我们可以实现一个新的元类型来包装评估operator.

评估与符号的比较=只有一条有效规则 - 两个值应该属于同一类型。你无法比较1和hello。之后,您只需确保这些值相同即可。


我们可以实现一个新的元类型来包装评估operator.


// Function signature for a "rule" of an operator.

type validFn func(left, right interface{}) bool


// Function signature for evaluating an operator comparison.

type evalFn func(left, right interface{}) bool


type operatorMeta struct {

    valid []validFn

    eval  evalFn

}

现在我们已经定义了类型,我们需要实现 的规则和比较函数Equals。


func sameTypes(left, right interface{}) bool {

    return reflect.TypeOf(left).Kind() == reflect.TypeOf(right).Kind()

}


func equals(left, right interface{}) bool {

    return reflect.DeepEqual(left, right)

}

惊人的!因此,我们现在可以验证两个值是否属于同一类型,如果是,我们可以将它们相互比较。难题的最后一部分是将运算符映射到其适当的规则和评估,并具有执行所有这些逻辑的函数。


var args = map[Operator]operatorMeta{

    Equals: {

        valid: []validFn{sameTypes},

        eval:  equals,

    },

}


func compare(o Operator, left, right interface{}) (bool, error) {

    opArgs, ok := args[o]

    if !ok {

        // You haven't implemented logic for this operator.

    }


    for _, validFn := range opArgs.valid {

        if !validFn(left, right) {

            // One of the rules were not satisfied.

        }

    }


    return opArgs.eval(left, right), nil

}

让我们总结一下到目前为止我们所得到的:

  • 将基本比较抽象为运算符

  • 创建了一种方法来验证一对对于运算符是否有效。

  • 创建了一种在给定两个值的情况下评估运算符的方法。

(去游乐场)

我希望我能对您如何解决这个问题提供一些见解。这是一个简单的想法,但需要一些样板才能正常工作。

祝你好运!


查看完整回答
反对 回复 2023-08-07
  • 1 回答
  • 0 关注
  • 71 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信