英文:
Abstract GET, read, unmarshal logic away
问题
我的应用程序执行了大量的API调用,我正在尝试消除其中的一些重复代码。从概念上讲,以下步骤在每次调用中都会重复执行:
- 发送GET请求
- 检查错误
- 读取响应的主体内容
- 检查错误
- 反序列化为目标结构体
- 检查错误
- 返回目标结构体
所有调用之间唯一的显著区别就是目标结构体。
在代码中,它看起来像这样:
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 // 这是唯一的真正区别!
err = json.Unmarshal(body, &users)
if err != nil {
return nil, err
}
return users, nil
}
我希望能够像这样使用getUsers(url, users)
和getProjects(url, projects)
。
我尝试过使用一个接受interface{}
类型参数的函数,然后稍后将其转换回正确的类型,但是没有成功:
func request(url string, target interface{}) (interface{}, error) {
// 执行与上述相同的逻辑。除了:
err = json.Unmarshal(body, &target)
// ...
return target, nil
}
然后可以这样做:
var users []User
result, err := request(url, users)
v, ok := result.([]User)
我有一种感觉,这应该是可行的...
英文:
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:
- Do a GET request
- Check for errors
- Read the body of the response
- Check for errors
- Deserialize into target struct
- Check for errors
- Return target struct
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...
答案1
得分: 0
不要使用interface{}
的地址,它已经包含了解组所需的指针。
func request(url string, target interface{}) (interface{}, error) {
// 获取响应
err := json.Unmarshal(body, target)
...
}
英文:
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)
...
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论