有没有一种方法可以取消阻止读取?

时间:2017-05-30 19:52:52

标签: go

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

理想情况下,我希望避免解析命令的StdoutPipe的输出,因为如果login命令的字符串发生变化,我的代码会很脆弱并容易出错。

loginCmd := exec.Command("login")
stdin , err := loginCmd.StdinPipe()
if err != nil {
    return err
}

out, err := loginCmd.StdoutPipe()

if err != nil {
    return err
}

if err := loginCmd.Start(); err != nil {
    return err
}

ctx, cancel := context.WithCancel(context.TODO())
var done sync.WaitGroup
done.Add(1)
ready := make(chan bool, 1)
defer cancel()
go func(ctx context.Context) {
    reader := bufio.NewReader(os.Stdin)
    for {
        select {
        case <- ctx.Done():
            done.Done()
            return
        default:
            //blocks on this line, if a close can unblock the read, then it should exit normally via the ctx.Done() case
            line, err :=reader.ReadString('\n')
            if err != nil {
                fmt.Println("Error: ", err.Error())
            }
            stdin.Write([]byte(line))
        }
    }
}(ctx)

var bytesRead = 4096
output := make([]byte, bytesRead)
reader := bufio.NewReader(out)
for err == nil {
    bytesRead, err = reader.Read(output)
    if err != nil && err != io.EOF {
        return err
    }
    fmt.Printf("%s", output[:bytesRead])
}

if err := loginCmd.Wait(); err != nil {
    return err
}
cancel()
done.Wait()

0 个答案:

没有答案
相关问题