文档net/http包含以下示例:
resp, err := http.Get("http://example.com/")
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
fmt.Printf("%s", body)
Run Code Online (Sandbox Code Playgroud)
Close返回一个error,但没有检查.这里有什么我想念的吗?在go中经常强调检查每个错误的重要性,但我看到这种defer resp.Body.Close()模式很多,没有错误检查.
Adr*_*ian 14
有两件事需要考虑:如果你检查它并且出现错误,你会怎么做?而且,如果出现错误会有什么副作用?
在大多数情况下,对于关闭响应机构,这两个问题的答案都是......绝对没有.如果出现错误并且错误没有明显影响,那么你什么都不做,没有理由检查它.
另请注意,Close()为了实现io.Closer接口,返回错误; 该函数不一定会返回错误.您需要检查源以确定是否存在错误情况.
这是使用的缺点 defer
建议您作为负责任的开发人员,检查所有可能的容易出错的点,并尽可能优雅地处理它们。
您可以在处理这种情况时选择以下选项:
不要使用defer,而是在完成响应主体后手动调用close,然后简单地检查是否有错误。
创建一个包装结束和错误检查代码的匿名函数。像这样:
defer func() {
err := resp.Body.Close()
if err != nil {
log.Fatal(err)
}
}()
Run Code Online (Sandbox Code Playgroud)
避免
panics在程序中使用。尝试通过执行某些操作或至少记录错误来优雅地处理错误。
要添加到 @Mihailo 选项 #2,请将其称为选项 #2.1 定义函数,dclose()如下所示:
func dclose(c io.Closer) {
if err := c.Close(); err != nil {
log.Fatal(err)
}
}
Run Code Online (Sandbox Code Playgroud)
像这样使用:
defer dclose(resp.Body)
Run Code Online (Sandbox Code Playgroud)
另外,在您的代码中,检查err!=nil可以声明:
func errcheck(err error) {
if err != nil {
log.Fatal(err)
}
}
Run Code Online (Sandbox Code Playgroud)
然后使用:
errcheck(err)
Run Code Online (Sandbox Code Playgroud)
那么你的代码就变成:
resp, err := http.Get("http://example.com/")
errcheck(err)
defer dclose(resp.Body)
body, err := ioutil.ReadAll(resp.Body)
errcheck(err)
fmt.Printf("%s", string(body))
Run Code Online (Sandbox Code Playgroud)
恕我直言,也许更干净一点?但我会等待go爱好者纠正我并强调缺点。
编辑
谢谢!@RayfenWindspear
请更换log.Fatal(err)以log.Println(err)避免不必要的恐慌。
编辑2
dclose()以避免与 go 混淆close()
玩得开心!