内容简介:针对除了Get以外的请求第二次请求会出错原因是第一次请求后req.Body已经读取到结束位置,所以第二次请求时无法再读取body,
针对除了Get以外的请求
package main
import (
"net/http"
"strings"
)
func main(){
reader := strings.NewReader("hello")
req,_ := http.NewRequest("POST","http://www.abc.com",reader)
client := http.Client{}
client.Do(req) // 第一次会请求成功
client.Do(req) // 请求失败
}
第二次请求会出错
http: ContentLength=5 with Body length 0
原因是第一次请求后req.Body已经读取到结束位置,所以第二次请求时无法再读取body,
解决方法:重新定义一个ReadCloser的实现类替换req.Body
package reader
import (
"io"
"net/http"
"strings"
"sync/atomic"
)
type Repeat struct{
reader io.ReaderAt
offset int64
}
// Read 重写读方法,使每次读取request.Body时能从指定位置读取
func (p *Repeat) Read(val []byte) (n int, err error) {
n, err = p.reader.ReadAt(val, p.offset)
atomic.AddInt64(&p.offset, int64(n))
return
}
// Reset 重置偏移量
func (p *Repeat) Reset(){
atomic.StoreInt64(&p.offset,0)
}
func (p *Repeat) Close() error {
// 因为req.Body实现了readcloser接口,所以要实现close方法
// 但是repeat中的值有可能是只读的,所以这里只是尝试关闭一下。
if p.reader != nil {
if rc, ok := p.reader.(io.Closer); ok {
return rc.Close()
}
}
return nil
}
func doPost() {
client := http.Client{}
reader := strings.NewReader("hello")
req , _ := http.NewRequest("POST","http://www.abc.com",reader)
req.Body = &Repeat{reader:reader,offset:0}
client.Do(req)
// 将偏移量重置为0
req.Body.(*Repeat).Reset()
client.Do(req)
}
这样就不会报错了,因为也重写了Close()方法,所以同时也解决了request重用时,req.Body自动关闭的问题。
以上所述就是小编给大家介绍的《Golang http.Request复用》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Beginning ARKit for iPhone and iPad
Wallace Wang / Apress / 2018-11-5 / USD 39.99
Explore how to use ARKit to create iOS apps and learn the basics of augmented reality while diving into ARKit specific topics. This book reveals how augmented reality allows you to view the screen on ......一起来看看 《Beginning ARKit for iPhone and iPad》 这本书的介绍吧!