My application does a whole lot of API calls and I'm trying to get rid of some duplication surrounding that. Conceptually the following steps are repeated every single time:
The only significant difference between all the calls is the target struct. In code it looks something like this:
func getUsers() ([]User, error) {
resp, err := http.Get(someUrl)
if err != nil {
return nil, err
}
if resp.StatusCode != 200 {
return nil, errors.New("Search return non 200 status code")
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var users []User // This is the only real difference!
err = json.Unmarshal(body, &users)
if err != nil {
return nil, err
}
return users, nil
}
I would love to do something like getUsers(url, users)
and getProjects(url, projects)
.
I've been trying with a function which takes a interface{}
and cast it later to the correct type again but to no avail:
func request(url string, target interface{}) (interface{}, error) {
// do all the same logic as above. Except:
err = json.Unmarshal(body, &target)
// ...
return target, nil
}
And then do something like:
var users []User
result, err := request(url, users)
v, ok := result.([]User)
I have the feeling this should be possible...
Don't use the address of the interface{}
, it already contains the pointer needed for unmarshaling.
func request(url string, target interface{}) (interface{}, error) {
// get response
err = json.Unmarshal(body, target)
...