【问题标题】:Access HTTP response as string in Go在 Go 中以字符串形式访问 HTTP 响应
【发布时间】:2016-12-05 01:09:00
【问题描述】:

我想解析 Web 请求的响应,但我无法将其作为字符串访问。

func main() {
    resp, err := http.Get("http://google.hu/")
    if err != nil {
        // handle error
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)

    ioutil.WriteFile("dump", body, 0600)

    for i:= 0; i < len(body); i++ {
        fmt.Println( body[i] ) // This logs uint8 and prints numbers
    }

    fmt.Println( reflect.TypeOf(body) )
    fmt.Println("done")
}

如何以字符串形式访问响应? ioutil.WriteFile 将响应正确写入文件。

我已经检查了包参考,但它并没有真正的帮助。

【问题讨论】:

    标签: networking go


    【解决方案1】:

    bs := string(body) 应该足以给你一个字符串。

    从那里,您可以将其用作常规字符串。

    有点像in this thread
    (在Go 1.16 -- Q1 2021 -- ioutil deprecation之后更新:ioutil.ReadAll() => io.ReadAll()):

    var client http.Client
    resp, err := client.Get(url)
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()
    
    if resp.StatusCode == http.StatusOK {
        bodyBytes, err := io.ReadAll(resp.Body)
        if err != nil {
            log.Fatal(err)
        }
        bodyString := string(bodyBytes)
        log.Info(bodyString)
    }
    

    另见GoByExample。

    如下所述(以及zzn 的answer),这是一个conversion(请参阅spec)。
    请参阅“How expensive is []byte(string)?”(相反的问题,但同样的结论适用)其中提到了zzzz:

    某些转换与强制转换相同,例如 uint(myIntvar),它只是重新解释到位的位。

    Sonia 补充:

    从一个字节片中创建一个字符串,肯定涉及到在堆上分配字符串。不变性属性迫使这一点。
    有时您可以通过使用 []byte 做尽可能多的工作然后在最后创建一个字符串来进行优化。 bytes.Buffer 类型通常很有用。

    【讨论】:

    • 谢谢。你有什么建议我怎么能自己弄清楚? string() 如何做到这一点?为什么用 reflect.TypeOf 看不到?
    • @TiborSzasz 这是一个简单的转换:见blog.golang.org/slices#TOC_12。
    • 对代码的一个小改进是使用http.StatusOK 而不是原始的200 值!
    • 我一直在这样做,发现我的请求正文末尾总是有一个换行符。这对于请求正文是正常的还是由ioutil.ReadAll() 引起的??
    【解决方案2】:

    您用于读取 http 正文响应的方法返回一个字节切片:

    func ReadAll(r io.Reader) ([]byte, error)
    

    official documentation

    您可以使用 []byte 将其转换为字符串

    body, err := ioutil.ReadAll(resp.Body)
    bodyString := string(body)
    

    【讨论】:

      【解决方案3】:

      string(byteslice) 会将字节切片转换为字符串,只要知道不只是简单的类型转换,还有内存拷贝。

      【讨论】:

        【解决方案4】:

        Go 1.16+ 更新(2021 年 2 月)

        弃用io/ioutil

        代码应该是

        var client http.Client
        resp, err := client.Get(url)
        if err != nil {
            log.Fatal(err)
        }
        defer resp.Body.Close()
        
        if resp.StatusCode == http.StatusOK {
            bodyBytes, err := io.ReadAll(resp.Body)
            // if u want to read the body many time
            // u need to restore 
            // reader := io.NopCloser(bytes.NewReader(bodyBytes))
            if err != nil {
                log.Fatal(err)
            }
            bodyString := string(bodyBytes)
            log.Info(bodyString)
        }
        

        参考

        1. https://golang.org/doc/go1.16#ioutil
        2. https://stackoverflow.com/a/52076748/2876087

        【讨论】:

        • 好点。我已经相应地更新了my answer。
        猜你喜欢
        • 1970-01-01
        • 2016-04-05
        • 2017-04-05
        • 1970-01-01
        • 2019-06-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多