Most go code I read contains frequent occurrences of the following pattern:
result1, err := failingOp1()
if err != nil {
return err
}
dependingResult, err := failingOp2(result1)
if err != nil {
return err
}
// do stuff with dependingResult
In functional programming we have the Either
monad and its cousins (e.g. Scala's Try
) that allow us to compose failing operations without constantly repeating ourselves.
Is there a go equivalent that helps decluttering the code?
Reading up a bit further, in particular this SO answer, it seems idiomatic go prefers handling errors at the call-site rather than propagating the potential error upwards (which the monadic approach favours).
Following this line of thinking:
func wrapFailingOp1() ResultType {
result1, err := failingOp1()
if err != nil {
return defaultRTOrPanic()
}
return result1
}
func wrapFailingOp2(result1 ResultType) DependingResultType {
dependingResult, err := failingOp2(result1)
if err != nil {
return defaultDRTOrPanic()
}
return dependingResult
}
x := wrapFailingOp1()
y := wrapFailingOp2(x)