Here, I have a conjunction expression involving some functions that return 2 values:
if _, ok := f(); ok {
if _, ok := g(); !ok {
if h() {
if _, ok := i(); ok {
doStuff()
}
}
}
}
Could I somehow avoid the nesting? Instead of nesting, could I write this as an expression in one line (I can't quite break or return early in this case)?
With a helper function, you can.
Create a helper function which returns the second bool
return value, e.g.:
func check(dummy interface{}, ok bool) bool {
return ok
}
And using it:
if check(f()) && check(g()) && h() && check(i()) {
doStuff()
}
Note that this is equivalent to the original code because the &&
operator is evaluated from left to right and it is using short-circuit evaluation: if any of the operands evaluate to false
, further operands (functions) will not be called.
This check()
function works for all functions that return 2 values and the 2nd is of type bool
(because any value can be assigned to a variable of type interface{}
).
This is covered in the Spec: Calls:
As a special case, if the return values of a function or method
g
are equal in number and individually assignable to the parameters of another function or methodf
, then the callf(g(parameters_of_g))
will invokef
after binding the return values ofg
to the parameters off
in order. The call off
must contain no parameters other than the call ofg
, andg
must have at least one return value. Iff
has a final...
parameter, it is assigned the return values ofg
that remain after assignment of regular parameters.
Note: since the first parameter in check()
is not used, we can even use the blank identifier when naming it which will make it obvious that we don't use that parameter:
func check(_ interface{}, ok bool) bool {
return ok
}
Avoid deep nesting or long conditionals running off the right side of the page with a function. For example,
package main
func f() (int, bool) { return 1, true }
func g() (int, bool) { return 1, true }
func h() bool { return true }
func i() (int, bool) { return 1, true }
func doStuff(f, g, i int) int { return f + g + i }
func andDoStuff() {
ff, ok := f()
if !ok {
return
}
gg, ok := g()
if !ok {
return
}
if ok := h(); !ok {
return
}
ii, ok := i()
if !ok {
return
}
doStuff(ff, gg, ii)
}
func main() {
andDoStuff()
}