It is possible to express what you have as a map. The basic setup here is, no matter which path you go down, you get some function that you can call with no parameters, and it always returns the same type (error). I might explicitly pass the args in.
The high-level structure of this is to have a map of function names to functions, then call the selected function.
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)
The map syntax gets kind of verbose
funcMap := map[string]func([]string) error{
"queryProduce": func(args []string) error {
return s.queryProduce(APIstub, args)
},
"initLedger": func(_ []string) error {
return s.initLedger(APIstub)
},
}
The map approach is better if you're ever going to call this in multiple places, or you want a separate validation step that some name would be defined if used, or if the actual list of functions is dynamic (you can add or remove things from the map at runtime). The inconsistent method signatures do introduce a complication and making everything consistent would help here (make functions like initLedger take an argument list even if it's unused).
In ordinary code I'd expect the switch form from @icza's answer to be more idiomatic.