duandang6111 2016-07-31 08:15
浏览 223

为什么golang中fasthttp的func Get具有`dst`参数?

I found fasthttp godoc as fellow:

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.

But, when I run fellow code

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 does not have "ok100", and dst is still "ok100". why?

  • 写回答

1条回答 默认 最新

  • douqiandai4327 2016-07-31 15:31
    关注

    Looking at the code where it is used in fasthttp's client.go func clientGetURLDeadlineFreeConn (line 672), you can see that if there is a timeout, dst's contents are copied to body at line 712. So based on what I read in the code (and debugged with Delve using your code), I saw that dst doesn't get updated in this usage. It seems that it can be used to provide default content to body in the event of a timeout - probably worth a direct question to fasthttp's author for more detail.

    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
    

    }

    In client.go func doRequestFollowRedirects (line 743) it is used at line 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
    

    }

    评论

报告相同问题?

悬赏问题

  • ¥15 seatunnel-web使用SQL组件时候后台报错,无法找到表格
  • ¥15 fpga自动售货机数码管(相关搜索:数字时钟)
  • ¥15 用前端向数据库插入数据,通过debug发现数据能走到后端,但是放行之后就会提示错误
  • ¥30 3天&7天&&15天&销量如何统计同一行
  • ¥30 帮我写一段可以读取LD2450数据并计算距离的Arduino代码
  • ¥15 飞机曲面部件如机翼,壁板等具体的孔位模型
  • ¥15 vs2019中数据导出问题
  • ¥20 云服务Linux系统TCP-MSS值修改?
  • ¥20 关于#单片机#的问题:项目:使用模拟iic与ov2640通讯环境:F407问题:读取的ID号总是0xff,自己调了调发现在读从机数据时,SDA线上并未有信号变化(语言-c语言)
  • ¥20 怎么在stm32门禁成品上增加查询记录功能