如何在匿名函数中逐行扫描文件并将其传递到通道



我想编写一个函数,该函数从文件中读取行,然后发送到通道中进行进一步处理。我是新手,这是我想到的读者功能,主要是以下教科书示例:

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()函数中,我将文件指针传递到读取器函数中,并尝试以下耗尽OUT频道:

func main() {
    out := reader(*f)
    for range out {
        fmt.Println(<-out)
    }
}

我没有comilation或运行时错误,但是,输出是空的。如果我不将for循环放入goroutine中,我可以使用任何问题都通过reader()函数打印文件。

我此外,我尝试将扫描仪,通道或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
}

然后从范围子句中打印值,而不是在for循环中收到的第二个值:

func main() {
    out := reader(os.Args[1])
    for line := range out {
        fmt.Println(line)
    }
}

最新更新