【发布时间】:2020-01-29 01:05:06
【问题描述】:
我正在编写一个小脚本,它使用 bufio.Scanner 和 http.Request 以及 go 例程来并行计算单词和行数。
package main
import (
"bufio"
"fmt"
"io"
"log"
"net/http"
"time"
)
func main() {
err := request("http://www.google.com")
if err != nil {
log.Fatal(err)
}
// just keep main alive with sleep for now
time.Sleep(2 * time.Second)
}
func request(url string) error {
res, err := http.Get(url)
if err != nil {
return err
}
go scanLineWise(res.Body)
go scanWordWise(res.Body)
return err
}
func scanLineWise(r io.Reader) {
s := bufio.NewScanner(r)
s.Split(bufio.ScanLines)
i := 0
for s.Scan() {
i++
}
fmt.Printf("Counted %d lines.\n", i)
}
func scanWordWise(r io.Reader) {
s := bufio.NewScanner(r)
s.Split(bufio.ScanWords)
i := 0
for s.Scan() {
i++
}
fmt.Printf("Counted %d words.\n", i)
}
正如scanLineWise 或多或少预期的那样,scalWordWise 将计算一个数字,而scalWordWise 将计算为零。这是因为scanLineWise 已经从req.Body 读取了所有内容。
我想知道:如何优雅地解决这个问题?
我的第一个想法是构建一个实现io.Reader 和io.Writer 的结构。我们可以使用io.Copy 读取req.Body 并将其写入writer。当扫描器从这个写入器读取数据时,写入器将复制数据而不是读取它。不幸的是,这只会随着时间的推移收集内存并打破流的整个想法......
【问题讨论】: