如何在匿名函数中逐行扫描文件并将其传递到通道
How to scan a file line by line in an anonymous function and pass it down a channel
我想编写一个函数,从文件中读取行,然后将其发送到通道以进行进一步处理。我是 Go 的新手,这里是 reader 函数,我想出了以下大部分教科书示例:
func reader(file string) <-chan string {
out := make(chan string)
f, err := os.Open(file)
if err != nil {
log.Fatal(err)
}
defer f.Close()
s := bufio.NewScanner(f)
go func() {
for s.Scan() {
out <- s.Text()
}
close(out)
}()
return out
}
在 main()
函数中,我将一个文件指针传递给 reader 函数,并尝试按如下方式排出输出通道:
func main() {
out := reader(*f)
for range out {
fmt.Println(<-out)
}
}
我没有收到编译或运行时错误,但是输出为空。如果我不将 for 循环放入 goroutine 中,我可以使用 reader()
函数打印文件 w/o 任何问题。
我还尝试将 reader()
函数中的扫描器、通道或两者都传递给匿名函数。但这并没有解决问题。谁能解释为什么此代码不起作用以及如何补救?
您正在关闭文件,然后再阅读它。
您只是每隔一行打印一次。
将延迟移动到实际发生读取的闭包中。
func reader(file string) <-chan string {
out := make(chan string)
f, err := os.Open(file)
if err != nil {
log.Fatal(err)
}
s := bufio.NewScanner(f)
go func() {
defer f.Close()
defer close(out)
for s.Scan() {
out <- s.Text()
}
if err := s.Err(); err != nil {
fmt.Println("error reading file:", err)
}
}()
return out
}
然后打印 range 子句中的值,而不是 for 循环中收到的第二个值:
func main() {
out := reader(os.Args[1])
for line := range out {
fmt.Println(line)
}
}
我想编写一个函数,从文件中读取行,然后将其发送到通道以进行进一步处理。我是 Go 的新手,这里是 reader 函数,我想出了以下大部分教科书示例:
func reader(file string) <-chan string {
out := make(chan string)
f, err := os.Open(file)
if err != nil {
log.Fatal(err)
}
defer f.Close()
s := bufio.NewScanner(f)
go func() {
for s.Scan() {
out <- s.Text()
}
close(out)
}()
return out
}
在 main()
函数中,我将一个文件指针传递给 reader 函数,并尝试按如下方式排出输出通道:
func main() {
out := reader(*f)
for range out {
fmt.Println(<-out)
}
}
我没有收到编译或运行时错误,但是输出为空。如果我不将 for 循环放入 goroutine 中,我可以使用 reader()
函数打印文件 w/o 任何问题。
我还尝试将 reader()
函数中的扫描器、通道或两者都传递给匿名函数。但这并没有解决问题。谁能解释为什么此代码不起作用以及如何补救?
您正在关闭文件,然后再阅读它。
您只是每隔一行打印一次。
将延迟移动到实际发生读取的闭包中。
func reader(file string) <-chan string {
out := make(chan string)
f, err := os.Open(file)
if err != nil {
log.Fatal(err)
}
s := bufio.NewScanner(f)
go func() {
defer f.Close()
defer close(out)
for s.Scan() {
out <- s.Text()
}
if err := s.Err(); err != nil {
fmt.Println("error reading file:", err)
}
}()
return out
}
然后打印 range 子句中的值,而不是 for 循环中收到的第二个值:
func main() {
out := reader(os.Args[1])
for line := range out {
fmt.Println(line)
}
}