我有下一个代码:
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')
}
有人可以解释为什么第一个解决方案具有这种行为吗?
最佳答案
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/