我找到了fasthttp godoc作为同事:
func Get
func Get(dst []byte, url string) (statusCode int, body []byte, err error)
Get appends url contents to dst and returns it as body.
The function follows redirects. Use Do* for manually handling redirects.
New body buffer is allocated if dst is nil.
但是,当我运行同事代码时
package main
import (
"fmt"
fh "github.com/valyala/fasthttp"
)
func main() {
url := "https://www.okcoin.cn/api/v1/ticker.do?symbol=btc_cny"
dst := []byte("ok100")
_, body, err := fh.Get(dst, url)
if err != nil {
fmt.Println(err)
}
fmt.Println("body:", string(body))
fmt.Println("dst:", string(dst))
}
body没有"ok100",dst仍然是"ok100"。为什么?
查看fasthttp的client.go func clientGetURLeadlineFreeConn中使用的代码(第672行),您可以看到,如果出现超时,dst的内容将在第712行复制到body。因此,根据我在代码中读到的内容(并使用您的代码使用Delve进行调试),我发现dst在这种用法中不会更新。它似乎可以用于在超时的情况下向主体提供默认内容——可能值得直接向fasthttp的作者询问更多细节。
func clientGetURLDeadlineFreeConn(dst []byte, url string, deadline time.Time, c clientDoer) (statusCode int, body []byte, err error) {
timeout := -time.Since(deadline)
if timeout <= 0 {
return 0, dst, ErrTimeout
}
var ch chan clientURLResponse
chv := clientURLResponseChPool.Get()
if chv == nil {
chv = make(chan clientURLResponse, 1)
}
ch = chv.(chan clientURLResponse)
req := AcquireRequest()
// Note that the request continues execution on ErrTimeout until
// client-specific ReadTimeout exceeds. This helps limiting load
// on slow hosts by MaxConns* concurrent requests.
//
// Without this 'hack' the load on slow host could exceed MaxConns*
// concurrent requests, since timed out requests on client side
// usually continue execution on the host.
go func() {
statusCodeCopy, bodyCopy, errCopy := doRequestFollowRedirects(req, dst, url, c)
ch <- clientURLResponse{
statusCode: statusCodeCopy,
body: bodyCopy,
err: errCopy,
}
}()
tc := acquireTimer(timeout)
select {
case resp := <-ch:
ReleaseRequest(req)
clientURLResponseChPool.Put(chv)
statusCode = resp.statusCode
body = resp.body
err = resp.err
case <-tc.C:
body = dst
err = ErrTimeout
}
releaseTimer(tc)
return statusCode, body, err
}
在client.go func doRequestFollowRedirects(第743行)中,它用于第748行:bodyBuf.B=dst
func doRequestFollowRedirects(req *Request, dst []byte, url string, c clientDoer) (statusCode int, body []byte, err error) {
resp := AcquireResponse()
bodyBuf := resp.bodyBuffer()
resp.keepBodyBuffer = true
oldBody := bodyBuf.B
bodyBuf.B = dst
redirectsCount := 0
for {
req.parsedURI = false
req.Header.host = req.Header.host[:0]
req.SetRequestURI(url)
if err = c.Do(req, resp); err != nil {
break
}
statusCode = resp.Header.StatusCode()
if statusCode != StatusMovedPermanently && statusCode != StatusFound && statusCode != StatusSeeOther {
break
}
redirectsCount++
if redirectsCount > maxRedirectsCount {
err = errTooManyRedirects
break
}
location := resp.Header.peek(strLocation)
if len(location) == 0 {
err = errMissingLocation
break
}
url = getRedirectURL(url, location)
}
body = bodyBuf.B
bodyBuf.B = oldBody
resp.keepBodyBuffer = false
ReleaseResponse(resp)
return statusCode, body, err
}