I am working on a ETL type application and a large majority of the error handling I do is just retrying API requests until they succeed (they randomly fail on occasion due to connection etc.). Therefore I have noticed a lot of code duplication that looks a lot like
for err != nil {
a,b,err = myfunc(c, d, e)
}
return a, b
So basically just keep doing the function until the error goes away (I put a sleep and other error checking as necessary as well to avoid rate limiting).
What I would like to do is simplify this to just one function that takes an arbitrary function, finds the error type in its output (if it has one) and runs it recursively until err!=nil. My problem is that although go seems to let you use any (interface{}) as an input it is not variadic on function definitions e.g. (type func(a int) (int, int, error)) as the type func(...any) []any
I am wondering if this is impossible to do in go and if so any suggestions to get around it/get similar functionality more idiomatically.
Trying to test with something like this but the compiler does not like it.
func main() {
Deal(SometimesFail, 10)
}
func Deal(f func(...any) []any, inputs ...any) []any {
outputs := f(inputs)
for _, val := range outputs {
err, ok := val.(error)
if ok {
for err != nil {
outputs = Deal(f, inputs...)
}
return outputs
}
continue
}
return outputs
}
func SometimesFail(a int) (int, int, error) {
random := rand.Intn(a)
if random%2 == 0 {
return random, random, nil
} else {
return random, random, errors.New("error")
}
}
I guess what I could do to get around this is create a type for each function out/input scheme and allow the generic function to take any of these. This would keep the code duplication at a minimum while still achieving the goal.