使用停止通道停止 bufio.Scanner

Mic*_*dry 5 go

我正在写一些os.Stdin使用bufio.Scanner类似读取行的东西:

for s.scanner.Scan() {
  line := s.scanner.Text()
  // process line
}
Run Code Online (Sandbox Code Playgroud)

这是在 goroutine 中运行的,我希望能够在chan struct{}关闭时停止它。然而,由于Scan阻塞直到有另一条线,我不知道如何停止它,如果没有更多输入,它会无限期地阻塞。

任何人都可以指出我正确的方向吗?

fer*_*mas 5

通过再创建一个间接并忽略底层,我们就可以停止了。

// actual reading, converts input stream to a channel
func readUnderlying(lines chan interface{}) {
    s := bufio.NewScanner(os.Stdin)
    for s.Scan() {
        lines <- s.Text()
    }
    lines <- s.Err()
}

func read(stop chan struct{}) {
    input := make(chan interface{}) // input stream
    go readUnderlying(input) // go and read
    for {
        select { // read or close
        case lineOrErr := <-input:
            fmt.Println(lineOrErr)
        case <-stop:
            return
        }
    }
}

func main() {
    stop := make(chan struct{})
    go read(stop)

    // wait some to simulate blocking
    time.Sleep(time.Second * 20) // it will print what is given
    close(stop)
    time.Sleep(time.Second * 20) // stopped so no more processing
}
Run Code Online (Sandbox Code Playgroud)

  • @MichaelBaldry 是的,并不完美,但消耗的资源最少。根据具体情况,更简单的解决方案可能是关闭“os.Stdin”,因为它是“io.Closer”。 (3认同)