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

我正在尝试对cli应用程序进行功能测试,类似于这种方式。


当命令在命令提示符下询问一些输入时,我将它们放在文件中并将其设置为os.Stdin。


cmd := exec.Command(path.Join(dir, binaryName), "myArg")

tmpfile := setStdin("TheMasterPassword\nSecondAnswer\n12121212\n")

cmd.Stdin = tmpfile

output, 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)

        }

    }

}

您能帮我找出问题所在吗?非常感谢!



慕桂英4014372
浏览 342回答 1
1回答

幕布斯7119047

它几乎看起来您的应用程序喜欢你的电话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()(使用默认的行拆分功能)将在返回行之前先去除该定界符。这也是您可以利用的简化方式。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go