在《 》中,我们已经介绍了几个一看就会一做就错的问题,下面我接着介绍另外几个问题。
body参数只能读取一次
使用过gin框架的人都是知道,读取body参数可以使用
ioutil.ReadAll(c. request .Body)
方法。但是有一次我发现,我在中间件里读取了body参数,打印了日志后,再在后续逻辑中使用
ioutil.ReadAll(c.Request.Body)
读取body参数,就读取不到了。后面研究gin的源代码才发现,body参数读取一次后就会被从request里删除,如果想读取多次,必须将读取的内容再写到
c.Request.Body
中去。如下:
这样后续操作才可以使用
ioutil.ReadAll(c.Request.Body)
重复读取。
使用resp.Body.Close()关闭 HTTP 响应体失败
在Golang中,使用 HTTP 标准库发起请求、获取响应时,即使你不从响应中读取任何数据或响应为空,都需要手动关闭响应体。但是有时候你会发现即使调了
resp.Body.Close()
方法,但是HTTP 响应体还是没有关闭,并且还发生了panic。之所以这样,是因为 resp 为nil,这样
resp.Body.Close()
就相当于调用了不存在的方法,因此会panic。
正确的做法应该是先检查 HTTP 响应是否为 nil,如果不为 nil ,才调用
resp.Body.Close()
来关闭响应体,如下:
recover只能恢复当前协程的Panic
在Golang中,捕获异常相对来说比较麻烦。因为它不能像在PHP中那样,只要在最外层使用try…catch就可以捕获所有异常。在Golang中,你需要一层一层的去使用defer…recover方法,而且最重要的是这个方法只能用于恢复所在协程的Panic,跨协程的Panic是无法恢复的。如下:
这段代码最终就无法完整地执行下去,因为其中一个协程必然会发生panic,这样就会导致整个应用挂掉,其它协程也随即跟着停止执行。