GoLang newbie here. I'm working on a project that reaches out to stripe and pulls the contents of different stripe tables (Product and Plan, for example). Eventually, I will be pulling data from 40-50 tables at Stripe, so I'm looking for ways to keep things maintainable.
Currently, I have functions that pull all the data I need for each table. By and large the functions for each table are the same, with the differences being building iterators and getting the data from a particular table.
Here are the functions. I stripped out all the things not pertinent to the question for clarity.
func getAllCoupon(folderName string) {
// do a bunch of setup stuff, init some vars, etc
stripeIter := getCouponIter("")
for okToContinue {
lastId := ""
for stripeIter.Next() && okToContinue {
p := stripeIter.Coupon()
// do some things with p
}
}
if pageLineCount == 0 {
okToContinue = false
} else {
stripeIter = getCouponIter(lastId)
}
}
. . .
}
func getCouponIter(id string) *coupon.Iter {
params := &stripe.CouponListParams{}
params.Filters.AddFilter("limit", "", config.Config.Input.StripeMaxPageSize)
if id != "" {
params.Filters.AddFilter("starting_after", "", id)
}
return coupon.List(params)
}
So rather than have 40-50 copies of getAll(), I'd like to have one, and pass in a function that yields an iterator - getCouponIter in this case.
I have looked into the stripe package code, and attempted to change the getAll function signature to include a parameter:
func getAllCoupon(folderName string, getIter func(string) *stripe.Iter)
And with some tweaking, I can get everything to line up. Except the return type from getCouponIter. The return type from that func is the return type of *coupon.Iter.
So, I'm curious. If I want to wind up with just one GetAll function and just pass in a function that queries stripe and passes back an iterator, how should I do that?
Edit: hanzo rightfully pointed out that this isn't really related to stripe payments, other than I have to use their framework to iterate over their returned data. It's more related to how I abstract the iterators somehow so I dont have 40 copies of the same function floating around.
Edit: Burak Serdar asked if the iterators all have the same functions. They do. The issue is that I'd like to pass a function to the getAll function that generates those iterators when needed. The iterators are paged (for events, for example), and so I might need to regenerate an iterator during the course of execution.
So I have functions that generate the iterators that look like this:
func getCouponIter(id string) *coupon.Iter
func getCustomerIter(id string) *customer.Iter
etc
I'd like to pass one of these iterator generator functions to the function that pulls all the data. The issue I'm running into is that to define an interface for these, they need the same return type (if I'm wrong, please tell me) and I cannot force these into returning anything other than what they are returning.
Whenever you need to copy/paste code, you can probably use generics.
I believe stripe iterators can be expressed using:
Using this, you can create a generic type-safe iterator:
Then, you can define
GetAllas:Call it as:
where
getSomethingreturns a Stripe iterator.There are probably missing pieces, but this should give you the general idea.