我有下一个代码:
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')
}
有人可以解释为什么第一种解决方案会出现这种行为吗?
答案 0 :(得分:2)
import "bufio"
func (b *Reader) ReadString(delim byte) (string, error)
ReadString读取直到输入中第一次出现delim, 返回包含数据的字符串,包括 分隔符。如果ReadString在找到之前遇到错误 分隔符,它返回错误和错误之前读取的数据 本身(通常是io.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")
}
答案 1 :(得分:0)
循环的结构是:
for init; condition; post { }
循环的init
部分在开头只调用一次。这意味着......
v, e := r.ReadString('\n')
...来自循环的部分仅被调用一次,这解释了为什么您的循环实现只读取r
的第一行以及为什么e
始终为nil
,从而导致无限循环。
你可能想做这样的事情:
for v, e := "", (error)(nil); e == nil; {
v, e = r.ReadString('\n')
fmt.Println(v)
}
或者如果这对你来说很奇怪,就像这样:
var v string
var e error
for ; e == nil; {
v, e = r.ReadString('\n')
fmt.Println(v)
}
更多信息: