Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Go 有没有取消阻塞读取的好方法?_Go - Fatal编程技术网

Go 有没有取消阻塞读取的好方法?

Go 有没有取消阻塞读取的好方法?,go,Go,我有一个必须通过操作系统运行的命令,我们称之为“login”,它是交互式的,因此需要我读取stdin并将其传递给命令的stdin管道,以便它正常工作。唯一的问题是goroutine阻塞了从stdin读取的数据,而我一直无法找到一种方法来取消Go中的一个读卡器,以使其不挂起阻塞调用。例如,从用户的角度来看,在命令看起来好像完成之后,您仍然有机会再次写入stdin(然后goroutine将通过阻塞读取并退出) 理想情况下,我希望避免必须解析来自命令StdoutPipe的输出,因为如果login命令的

我有一个必须通过操作系统运行的命令,我们称之为“login”,它是交互式的,因此需要我读取stdin并将其传递给命令的stdin管道,以便它正常工作。唯一的问题是goroutine阻塞了从stdin读取的数据,而我一直无法找到一种方法来取消Go中的一个读卡器,以使其不挂起阻塞调用。例如,从用户的角度来看,在命令看起来好像完成之后,您仍然有机会再次写入stdin(然后goroutine将通过阻塞读取并退出)

理想情况下,我希望避免必须解析来自命令StdoutPipe的输出,因为如果
login
命令的字符串发生更改,这会使我的代码变得脆弱,并且容易出错

loginCmd:=执行命令(“登录”)
stdin,err:=loginCmd.StdinPipe()
如果出错!=零{
返回错误
}
out,err:=loginCmd.StdoutPipe()
如果出错!=零{
返回错误
}
如果错误:=loginCmd.Start();呃!=零{
返回错误
}
ctx,cancel:=context.WithCancel(context.TODO())
var done sync.WaitGroup
完成。添加(1)
准备就绪:=制作(chan bool,1)
推迟取消
go func(ctx context.context){
reader:=bufio.NewReader(os.Stdin)
为了{
挑选{

对某些序列的输出进行大小写分析,表明轮到用户提供输入似乎更“正确”方法-基于超时的操作也很脆弱,因为它a)意味着你的程序不能比超时更快地运行;b)当它分叉的程序运行速度比预期慢时,可能会出现错误行为。退出
loginCmd
后,你还做了什么吗?如果没有,你可以退出你的Go程序,而不是取消操作上下文并等待goroutine完成。@AndySchweig很遗憾,是的,这个方法是一个较大函数的一小部分。您不能取消对Stdin的读取,只需让goroutine保持运行,并确保它在以后完成时不会影响程序。@sreya:不,因为Stdin是一个tty。解决这个问题的唯一方法是不使用直接阅读,并使用syscall包在fd上选择(或等效),然后轮询或将其与可用于发出退出信号的管道配对(即“自管道技巧”)。当您可以离开goroutine而不必担心它时,通常没有理由经历这些麻烦。解析某个序列的输出以指示轮到用户提供输入似乎更“正确”方法-基于超时的操作也很脆弱,因为它a)意味着你的程序不能比超时更快地运行;b)当它分叉的程序运行速度比预期慢时,可能会出现错误行为。退出
loginCmd
后,你还做了什么吗?如果没有,你可以退出你的Go程序,而不是取消操作上下文并等待goroutine完成。@AndySchweig很遗憾,是的,这个方法是一个较大函数的一小部分。您不能取消对Stdin的读取,只需让goroutine保持运行,并确保它在以后完成时不会影响程序。@sreya:不,因为Stdin是一个tty。解决这个问题的唯一方法是不使用直接阅读,并使用syscall包在fd上选择(或等效),然后轮询或将其与可用于发出退出信号的管道配对(即“自我管道技巧”)。当您可以离开goroutine而不必担心它时,通常没有理由经历这些麻烦。