终端中的Go应用程序输入超时

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

timeout for input in terminal go application

问题

我正在尝试制作一个终端golang应用程序,用户有4秒的时间输入内容。如果他输入得更快,就打印结果并再次要求他在4秒内输入。

如果用户在4秒内没有返回输入,程序必须写入time out并再次要求输入。

我的代码可以实现这个功能,但只能执行一次。在第一次超时后,即使用户在4秒内输入,也不会返回任何结果。我无法弄清楚为什么会这样。

代码如下:

package main

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"time"
)

var (
	result string
	err    error
)

func getInput(input chan string) {
	in := bufio.NewReader(os.Stdin)
	result, err := in.ReadString('\n')
	if err != nil {
		log.Fatal(err)
	}

	input <- result
}

func main() {
	for {
		fmt.Println("请输入内容:")
		input := make(chan string, 1)
		go getInput(input)

		select {
		case i := <-input:
			fmt.Println("结果:")
			fmt.Println(i)
		case <-time.After(4000 * time.Millisecond):
			fmt.Println("超时")
		}
	}
}

输出结果:

请输入内容:
123
结果:
123

请输入内容:
2
结果:
2

请输入内容:
超时
请输入内容:
2
超时
请输入内容:
超时
请输入内容:

希望这可以帮助到你。

英文:

I am trying to make a terminal golang application, where a user has 4 seconds to input something. If he inputted something faster, print result and ask him input again for 4 seconds.

If a user will not return input in 4 seconds, the program must write time out and ask him input again.

My code does this, but only once. After the first timeout it won't return any result even if a user was faster that 4 seconds. I cannot figure out why this is so.

The code

package main

import (
	&quot;bufio&quot;
	&quot;fmt&quot;
	&quot;log&quot;
	&quot;os&quot;
	&quot;time&quot;
)

var (
	result string
	err    error
)

func getInput(input chan string) {
	in := bufio.NewReader(os.Stdin)
	result, err := in.ReadString(&#39;\n&#39;)
	if err != nil {
		log.Fatal(err)
	}

	input &lt;- result
}

func main() {
	for {
		fmt.Println(&quot;input something&quot;)
		input := make(chan string, 1)
		go getInput(input)

		select {
		case i := &lt;-input:
			fmt.Println(&quot;result&quot;)
			fmt.Println(i)
		case &lt;-time.After(4000 * time.Millisecond):
			fmt.Println(&quot;timed out&quot;)
		}
	}
}

The output:

input something
123
result
123

input something
2
result
2

input something
timed out
input something
2
timed out
input something
timed out
input something

答案1

得分: 3

问题与您获取用户输入的方式有关。在超时时,您会生成一个新的go例程来请求输入,但之前生成的旧例程仍然存在,它会获取输入并将其发送到一个没有人再监听的通道中。

将其更改为以下内容将解决问题:

func getInput(input chan string) {
    for {
        in := bufio.NewReader(os.Stdin)
        result, err := in.ReadString('\n')
        if err != nil {
            log.Fatal(err)
        }

        input <- result
    }
}

func main() {
    input := make(chan string, 1)
    go getInput(input)

    for {
        fmt.Println("请输入:")

        select {
        case i := <-input:
            fmt.Println("结果:")
            fmt.Println(i)
        case <-time.After(4000 * time.Millisecond):
            fmt.Println("超时")
        }
    }
}

请注意,这只是代码的翻译部分,不包括任何其他内容。

英文:

The problem has to do with the way you're getting the user's input. On a timeout you spawn a new go routine asking for input, but the old one that you had spawned previously is still there grabbing input and sending it to a channel that no one is listening to any more.

Changing it to something like this would fix the problem:

func getInput(input chan string) {
    for {
        in := bufio.NewReader(os.Stdin)
        result, err := in.ReadString(&#39;\n&#39;)
        if err != nil {
            log.Fatal(err)
        }

        input &lt;- result
    }
}

func main() {
    input := make(chan string, 1)
    go getInput(input)

    for {
        fmt.Println(&quot;input something&quot;)

        select {
        case i := &lt;-input:
            fmt.Println(&quot;result&quot;)
            fmt.Println(i)
        case &lt;-time.After(4000 * time.Millisecond):
            fmt.Println(&quot;timed out&quot;)
        }
    }
}

huangapple
  • 本文由 发表于 2015年7月1日 02:53:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/31146205.html
匿名

发表评论

匿名网友

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

确定