我在多层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.")
}
答案 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
形式更加惯用。