我有下一个代码:

resp, err := http.Get("https://www.google.com")

if err != nil{
    panic(err)
}

r := bufio.NewReader(resp.Body)

for v, e := r.ReadString('\n'); e == nil; {
    fmt.Println(v)
}

因此,我想循环读取响应正文,但读者r无限读取Body的第一行。

同时,此代码可以正常工作:
v, e := r.ReadString('\n')
for e == nil {
    fmt.Println(v)
    v, e = r.ReadString('\n')
}

有人可以解释为什么第一个解决方案具有这种行为吗?

最佳答案

Package bufio

import "bufio"

func (*Reader) ReadString
func (b *Reader) ReadString(delim byte) (string, error)

ReadString读取直到输入中第一次出现delim为止,
返回一个字符串,该字符串包含直至(包括)
定界符。如果ReadString在找到
定界符,它返回错误之前读取的数据和错误
本身(通常为EOF)。如果且仅当ReadString返回err!= nil
返回的数据不以delim结尾。为了简单使用,请使用扫描仪
可能更方便。


这是XY problem:XY问题是在询问您尝试的解决方案,而不是您的实际问题。

您为什么不接受bufio.ReadString文档中给出的建议“简单使用,扫描仪可能会更方便”?

正确使用bufio.ReadString十分复杂,即使您知道如何使用for循环也是如此。参见函数reader

正确使用bufio.Scannner很简单,即使您不知道如何使用for循环也是如此。参见函数scanner

例如,
package main

import (
    "bufio"
    "fmt"
    "io"
    "net/http"
    "os"
    "strings"
)

func reader(url string) error {
    resp, err := http.Get(url)
    if err != nil {
        return err
    }
    defer resp.Body.Close()

    // ReadString
    r := bufio.NewReader(resp.Body)
    for {
        line, err := r.ReadString('\n')
        if len(line) == 0 && err != nil {
            if err == io.EOF {
                break
            }
            return err
        }
        line = strings.TrimSuffix(line, "\n")

        fmt.Println(line)

        if err != nil {
            if err == io.EOF {
                break
            }
            return err
        }
    }

    return nil
}

func scanner(url string) error {
    resp, err := http.Get(url)
    if err != nil {
        return err
    }
    defer resp.Body.Close()

    // Scanner
    s := bufio.NewScanner(resp.Body)
    for s.Scan() {
        line := s.Text()

        fmt.Println(line)

    }
    if s.Err() != nil {
        return err
    }

    return nil
}

func main() {
    url := "https://www.example.com"
    fmt.Println("\nReader:\n")
    err := reader(url)
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
    }
    fmt.Println("\nScanner:\n")
    err = scanner(url)
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
    }
    fmt.Println("\n")
}

游乐场:https://play.golang.org/p/e0WY_aNxW8

关于go - 在循环中进入bufio ReadString是无限的,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47479564/

10-11 20:20