为了账号安全,请及时绑定邮箱和手机立即绑定

将文件用作Stdin(Golang)时,在第二提示符下获得EOF

将文件用作Stdin(Golang)时,在第二提示符下获得EOF

Go
慕桂英4014372 2021-04-09 22:19:20
我正在尝试对cli应用程序进行功能测试,类似于这种方式。当命令在命令提示符下询问一些输入时,我将它们放在文件中并将其设置为os.Stdin。cmd := exec.Command(path.Join(dir, binaryName), "myArg")tmpfile := setStdin("TheMasterPassword\nSecondAnswer\n12121212\n")cmd.Stdin = tmpfileoutput, err := cmd.CombinedOutput()在setStdin刚刚创建TMPFILE,写在文件和返回字符串*os.File。现在,我希望TheMasterPassword是第一个输入,并且它正在运行。但是对于第二个输入总是会得到Critical Error: EOF。我用于询问和获取用户输入的功能:func Ask(question string, minLen int) string {    reader := bufio.NewReader(os.Stdin)    for {        fmt.Printf("%s: ", question)        response, err := reader.ReadString('\n')        ExitIfError(err)        if len(response) >= minLen {            return strings.TrimSpace(response)        } else {            fmt.Printf("Provide at least %d character.\n", minLen)        }    }}您能帮我找出问题所在吗?非常感谢!
查看完整描述

1 回答

?
幕布斯7119047

TA贡献1794条经验 获得超8个赞

它几乎看起来您的应用程序喜欢你的电话Ask(),每当你想一个单一的输入线。


在其中Ask()创建一个bufio.Reader要读取的内容os.Stdin。知道bufio.Reader-顾名思义-使用缓冲读取,这意味着它从其源读取的数据可能比其方法返回的数据更多(Reader.ReadString()在这种情况下)。这意味着,如果仅使用它来读取一个(或一些)行,而丢弃读取器,则会丢弃已缓冲的,未读取的数据。


因此,下次您Ask()再次致电尝试从中读取时os.Stdin,您将不会从上次中断的地方继续...


要解决这个问题,只有建立一个单一bufio.Reader的os.Stdin,它存储在例如一个全局变量,并且里面Ask(),总是用这种单一的读者。因此,缓冲和未读数据不会在Ask()调用之间丢失。当然,从多个goroutine调用该解决方案将无效,但从单个goroutine调用os.Stdin也不可行。


例如:


var reader = bufio.NewReader(os.Stdin)


func Ask(question string, minLen int) string {

}

另请注意,bufio.Scanner在您的情况下,使用起来会更容易。但是同样,bufio.Scanner可能还会从其源中读取比所需更多的数据,因此您也必须在bufio.Scanner此处使用共享。还要注意,Reader.ReadString()返回一个包含定界符(\n以您的情况为结尾的行)的字符串,您可能必须对其进行修剪,而Scanner.Text()(使用默认的行拆分功能)将在返回行之前先去除该定界符。这也是您可以利用的简化方式。


查看完整回答
反对 回复 2021-04-19
  • 1 回答
  • 0 关注
  • 350 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信