golang处理http response碰到的问题和需要注意的点

在Golang中处理HTTP响应时,一旦body被读取,再次尝试读取会发现为空。这是因为body实现了io.Closer接口,读取后有偏移量导致无法重新读取。解决方法是创建新的Reader。同时,客户端需确保关闭response body以避免内存泄露,而请求body则无需手动关闭,由net/http库自动处理。服务器端接收的request body也需要关闭。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在处理http response的时候,偶然发现,body读取之后想再次读取的时候,发现读不到任何东西。见下方代码:

response, err = ioutil.ReadAll(resp.Body)
    if err != nil {
        log.Println("ioutil ReadAll failed :", err.Error())
        return
    }

之后如果想再次ioutil.ReadAll(resp.Body)的时候会发现读到的是空。于是我决定去看一下这个resp.Body,发现它是一个io.ReadCloser接口,包含了ReaderCloser接口:

type ReadCloser interface {
    Reader
    Closer
}

于是我想到了文件,它也实现了io.Reader接口,所以用读文件试了下:

func readFile(path string)string{
    fi,err := os.Open(path)
    if err != nil{panic(err)}
    defer fi.Close()

    byte1,err := ioutil.ReadAll(fi)
    fmt.Println(string(byte1))

    byte2,err := ioutil.ReadAll(fi)
    fmt.Println(string(byte2))

    return string(fd)
}

发现结果是一致的,fmt.Println(string(fd2))打印不出任何结果。我猜测应该是ioutil.ReadAll()是有记录偏移量,所以会出现第二次读取读不到的情况。作为client端处理response的时候会碰到这个问题,作为server端要处理request body的时候,一样会遇到此问题,那么该如何解决这个问题呢?
有一个方法是再造一个io.ReadCloser,如下:

    fi2:= ioutil.NopCloser(bytes.NewBuffer(byte1))
    byte3,err := ioutil.ReadAll(fi2)
    fmt.Println(string(byte3))

此外,作为client端处理response的时候,有一点要注意的是,body一定要close,否则会造成GC回收不到,继而产生内存泄露。其实在go的官方源码注释中,也明确注明了response body需要调用方进行手动关闭:It is the caller's responsibility to close Body.

至于response body为什么需要进行关闭,这篇文章进行了解释:
https://studygolang.com/articles/9887

那么作为client端生成的request body,需不需要手动关闭呢,答案是不需要的,net/http中的func (c *Client) Do(req *Request) (*Response, error)会调用Close()

同样的,作为server端接收的request body,也是需要关闭,由Server自动进行关闭,The Server will close the request body. The ServeHTTP Handler does not need to.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值