How to read input from console in a non blocking way with Go?

huangapple go评论83阅读模式
英文:

How to read input from console in a non blocking way with Go?

问题

所以我有:

import (
    "bufio"
    "os"
)
//...
var reader = bufio.NewReader(os.Stdin)
str, err := reader.ReadString('\n')

但是reader.ReadString('\n')会阻塞执行。我想以非阻塞的方式读取输入。是否可以使用bufio包或Go的任何其他标准库包从os.Stdin实现非阻塞缓冲输入?

英文:

So I have:

import (
	"bufio"
	"os"
)
//...
var reader = bufio.NewReader(os.Stdin)
str, err := reader.ReadString('\n')

But reader.ReadString('\n') is blocking execution. I would like to read input in a non blocking way. Is it possible to achieve non blocking buffered input from os.Stdin using bufio package or any other std lib package from Go?

答案1

得分: 12

一般来说,Go语言中没有非阻塞IO API的概念。你可以通过使用goroutines来实现相同的功能。

以下是一个示例,由于Playground不允许使用stdin,所以这里模拟了stdin。

package main

import "fmt"
import "time"

func main() {
    ch := make(chan string)
    go func(ch chan string) {
        /* Uncomment this block to actually read from stdin
        reader := bufio.NewReader(os.Stdin)
        for {
            s, err := reader.ReadString('\n')
            if err != nil { // Maybe log non io.EOF errors, if you want
                close(ch)
                return
            }
            ch <- s
        }
        */
        // Simulating stdin
        ch <- "A line of text"
        close(ch)
    }(ch)

stdinloop:
    for {
        select {
        case stdin, ok := <-ch:
            if !ok {
                break stdinloop
            } else {
                fmt.Println("Read input from stdin:", stdin)
            }
        case <-time.After(1 * time.Second):
            // Do something when there is nothing read from stdin
        }
    }
    fmt.Println("Done, stdin must be closed")
}

你可以在这里查看示例代码。

英文:

In general there isn't a concept of non-blocking IO APIs in Go. You accomplish the same thing by using goroutines.

Here's an example on Play, stdin is simulated since play doesn't allow for it.

package main

import &quot;fmt&quot;
import &quot;time&quot;

func main() {
	ch := make(chan string)
	go func(ch chan string) {
		/* Uncomment this block to actually read from stdin
		reader := bufio.NewReader(os.Stdin)
		for {
			s, err := reader.ReadString(&#39;\n&#39;)
			if err != nil { // Maybe log non io.EOF errors, if you want
				close(ch)
				return
			}
			ch &lt;- s
		}
		*/
		// Simulating stdin
		ch &lt;- &quot;A line of text&quot;
		close(ch)
	}(ch)

stdinloop:
	for {
		select {
		case stdin, ok := &lt;-ch:
			if !ok {
				break stdinloop
			} else {
				fmt.Println(&quot;Read input from stdin:&quot;, stdin)
			}
		case &lt;-time.After(1 * time.Second):
			// Do something when there is nothing read from stdin
		}
	}
	fmt.Println(&quot;Done, stdin must be closed&quot;)
}

huangapple
  • 本文由 发表于 2014年11月30日 11:30:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/27209697.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定