In the simplified code example below, we perform tens of different API calls using the Go library from our vendor.
Vendor library provides us with a definition of API call bodies:
// body of api call A
type requestBodyA struct {
aa string
bb int32
}
// body of api call B
type requestBodyB struct {
id string
}
And with functions which performs the calls for us:
// fn performs api call A
func callCreateA(body requestBodyA) {
fmt.Println("Value of body is: ", body)
// makes api call using body requestBodyA
}
// fn performs api call B
func callCreateB(body requestBodyB) {
fmt.Println("Value of body is: ", body)
// makes another api call using body requestBodyB
}
We use those to create our own CRUD functions, where we read config files and perform create/read/update/delete calls:
func createA() {
bodyA := requestBodyA{
aa: "asdasfsd",
bb: 15,
}
// api retry loop
for i := 1; i <= 3; i++ {
// do some pre-checks (generic)
callCreateA(bodyA)
// check for errors (generic)
// check if error is recoverable (generic)
// if not return error (generic)
// if yes use the for loop and try the call again in 1,2,3,5,8,13, .. seconds (generic)
}
}
func createB() {
bodyB := requestBodyB{
id: "someUniqueId",
}
for i := 1; i <= 3; i++ {
// do some pre-checks (generic)
callCreateB(bodyB)
// check for errors (generic)
// check if error is recoverable (generic)
// if not return error (generic)
// if yes use the for loop and try the call again in 1,2,3,5,8,13, .. seconds (generic)
}
}
As you can see in functions createA
, createB
we repeat a lot of generic code (pre-checks, error handling, retry loop and lot more) in every CRUD fn we create. As we're dealing with 30+ resources and each have their own create, read, update, destroy API call function, we have the same code copied 100+ times.
I'd like to move all the generic stuff to some genericApiCaller() and give it the call body as one param and name or a pointer to the API call function as a second param.
Problem 1: callCreateA
and callCreateB
needs the "body" of different types. It would be way easier if they consume interface{}, but these functions are coming from vendor SDK and it would not be smart to modify them (update reasons, etc). How to assert "body interface{}" of genericApiCaller() to "body requestBodyA" or "body requestBodyB" dynamically? Runtime assertion is not possible in Go, but I didn't find any nice solution for it.
Problem2: How to pass functions with different kinds of parameters as a parameter to genericApiCaller()?
Any idea of how to approach it will be appreciated :-) Thank you very much.
https://play.golang.org/p/incf-NEaSJ3
Aucun commentaire:
Enregistrer un commentaire