如何用地图替换多个“ if-else-if”

时间:2019-08-01 08:58:05

标签: dictionary if-statement go

我在多层if-else-if条件上遇到了一个问题,所以我想通过使用地图来简化它。

请在if-else-if中查看下面的代码,该代码我要替换为地图。

function, args := APIstub.GetFunctionAndParameters()

if function == "queryProduce" {
    return s.queryProduce(APIstub, args)
} else if function == "initLedger" {
    return s.initLedger(APIstub)
} else if function == "createProduce" {
    return s.createProduce(APIstub, args)
} else if function == "queryAllProduces" {
    return s.queryAllProduces(APIstub)
} else if function == "changeProduceStatus" {
    return s.changeProduceStatus(APIstub, args)
}

return shim.Error("Invalid Smart Contract function name.")
}

2 个答案:

答案 0 :(得分:6)

对于您拥有switch的东西来说,这很好:

switch function {
case "queryProduce":
    return s.queryProduce(APIstub, args)
case "initLedger":
    return s.initLedger(APIstub)
case "createProduce":
    return s.createProduce(APIstub, args)
case "queryAllProduces":
    return s.queryAllProduces(APIstub)
case "changeProduceStatus":
    return s.changeProduceStatus(APIstub, args)
}

使用地图会很不方便,因为并非所有方法都具有相同的签名,但是您可以使用多个地图。

另一种解决方案可能是使用反射来调用方法,但是同样,处理不同的参数将很不方便。反射速度也较慢,更不用说您必须避免不允许不打算公开的调用方法。有关示例,请参见Call functions with special prefix/suffix

答案 1 :(得分:1)

可以表达您的地图。这里的基本设置是,无论您走哪条路径,都可以获得可以不带任何参数调用的函数,并且该函数始终返回相同的类型(error)。我可能会明确传入args

它的高级结构是将函数名称映射到函数,然后调用所选函数。

funcMap := map[string]func([]string) error{...}
funcName, args := APIstub.GetFunctionAndParameters()
f := funcMap[funcName]
if f == nil {
    f = func(_ []string) error {
        return shim.Error("Invalid Smart Contract function name.")
    }
}
return f(args)

地图语法有点冗长

funcMap := map[string]func([]string) error{
    "queryProduce": func(args []string) error {
        return s.queryProduce(APIstub, args)
    },
    "initLedger": func(_ []string) error {
        return s.initLedger(APIstub)
    },
}

如果要在多个位置调用此映射方法,或者希望使用一个单独的验证步骤(如果使用该名称,或者如果函数的实际列表是动态的,则可以定义一些名称),则映射方法会更好。或在运行时从地图中删除内容)。不一致的方法签名确实带来了复杂性,使所有内容保持一致将有助于解决问题(使initLedger之类的函数即使没有使用也要接受参数列表)。

在普通代码中,我希望@icza的回答中的switch形式更加惯用。