英文:
Problem with testing cli prompts interactively, scanner is not waiting for user input
问题
我尝试编写一个测试来验证命令行提示,模拟用户对某些程序输出的响应中的输入。
如何使scanner.Scan
等待其他写入?
我目前的代码如下:
b := &bytes.Buffer{}
fmt.Fprint(b, "0")
go func() {
time.Sleep(1 * time.Second)
for i := 1; i < 4; i++ {
fmt.Fprint(b, i)
time.Sleep(1 * time.Second)
}
}()
scanner := bufio.NewScanner(b)
for scanner.Scan() {
log.Print(scanner.Text())
}
if err := scanner.Err(); err != nil {
log.Println("扫描时出现问题:", err)
}
期望的结果是:0123
实际结果是:0
我尝试了一个使用io.Pipe
的版本
r, w := io.Pipe()
fmt.Fprint(w, "0")
go func() {
time.Sleep(1 * time.Second)
for i := 1; i < 4; i++ {
fmt.Fprint(w, i)
time.Sleep(1 * time.Second)
}
}()
scanner := bufio.NewScanner(r)
for scanner.Scan() {
log.Print(scanner.Text())
}
if err := scanner.Err(); err != nil {
log.Println("扫描时出现问题:", err)
}
结果:致命错误:所有goroutine都处于休眠状态-死锁!
英文:
I try to write a test to verify cli prompts, emulate user inputs in response to some program outputs.
How to make scanner.Scan
wait for the rest of the writes?
What I have so far:
b := &bytes.Buffer{}
fmt.Fprint(b, "0")
go func() {
time.Sleep(1 * time.Second)
for i := 1; i < 4; i++ {
fmt.Fprint(b, i)
time.Sleep(1 * time.Second)
}
}()
scanner := bufio.NewScanner(b)
for scanner.Scan() {
log.Print(scanner.Text())
}
if err := scanner.Err(); err != nil {
log.Println("problem while scanning:", err)
}
Expected result is: 0123
Actual result is: 0
I tried a version with io.Pipe
r, w := io.Pipe()
fmt.Fprint(w, "0")
go func() {
time.Sleep(1 * time.Second)
for i := 1; i < 4; i++ {
fmt.Fprint(w, i)
time.Sleep(1 * time.Second)
}
}()
scanner := bufio.NewScanner(r)
for scanner.Scan() {
log.Print(scanner.Text())
}
if err := scanner.Err(); err != nil {
log.Println("problem while scanning:", err)
}
result: fatal error: all goroutines are asleep - deadlock!
答案1
得分: 0
使用管道时,写入和读取是同步的。没有匹配的读取操作,写入操作无法完成。将第一个写入操作移到goroutine中,并关闭管道的写入端,以允许扫描器停止扫描。
r, w := io.Pipe()
go func() {
defer w.Close()
fmt.Fprint(w, "0")
time.Sleep(1 * time.Second)
for i := 1; i < 4; i++ {
fmt.Fprint(w, i)
time.Sleep(1 * time.Second)
}
}()
scanner := bufio.NewScanner(r)
for scanner.Scan() {
log.Print(scanner.Text())
}
if err := scanner.Err(); err != nil {
log.Println("扫描时出现问题:", err)
}
英文:
When using a pipe, writes and reads are synchronous. A Write cannot complete without a matching Read. Move the first write into the goroutine. And Close the writing end of the pipe to allow the scanner to stop scanning.
r, w := io.Pipe()
go func() {
defer w.Close()
fmt.Fprint(w, "0")
time.Sleep(1 * time.Second)
for i := 1; i < 4; i++ {
fmt.Fprint(w, i)
time.Sleep(1 * time.Second)
}
}()
scanner := bufio.NewScanner(r)
for scanner.Scan() {
log.Print(scanner.Text())
}
if err := scanner.Err(); err != nil {
log.Println("problem while scanning:", err)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论