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

时间:2017-09-07 14:16:06

标签: go anonymous-function

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

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函数,并尝试按如下方式排出out通道:

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

我没有编译或运行时错误,但输出为空。如果我没有将for循环放入goroutine,我可以使用reader()函数打印文件,无任何问题。

我还尝试将reader()功能中的扫描仪,频道或两者传递到匿名功能。但它并没有解决问题。任何人都可以解释为什么这段代码不起作用以及如何解决它?

1 个答案:

答案 0 :(得分:0)

您在阅读之前关闭了该文件。

你只是每隔一行打印一次。

将延迟移动到实际发生读取的闭包中。

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)
    }
}