the*_*T's 5 stdin user-input go
这是一个困扰我的问题.当从用户获得输入时,我想使用循环来要求用户重试,直到他们输入有效输入:
// user_input.go
package main
import (
"fmt"
)
func main() {
fmt.Println("Please enter an integer: ")
var userI int
for {
_, err := fmt.Scanf("%d", &userI)
if err == nil {
break
}
fmt.Println("Sorry, invalid input. Please enter an integer: ")
}
fmt.Println(userI)
}
Run Code Online (Sandbox Code Playgroud)
运行以上操作,如果用户输入有效输入,没问题:
请输入一个整数:
3
3
退出代码0,正常退出流程.
但是尝试输入一个字符串呢?
请输入一个整数:
什么?
对不起,输入无效.请输入一个整数:
抱歉,输入无效.请输入一个整数:
抱歉......
等等,它会逐个字符循环,直到字符串用完为止.即使输入一个字符循环两次,我假设它解析换行符.
无论如何,必须有一种方法在Go中冲洗Stdin?
PS如果没有这样的功能,您将如何解决它以提供相同的功能?我甚至都失败了......
唤醒一个老问题是不是很糟糕?
我更喜欢使用,fmt.Scanln
因为A)它不需要导入另一个库(例如阅读器)并且B)它不涉及显式的for循环。
func someFunc() {
fmt.Printf("Please enter an integer: ")
// Read in an integer
var i int
_, err := fmt.Scanln(&i)
if err != nil {
fmt.Printf("Error: %s", err.Error())
// If int read fails, read as string and forget
var discard string
fmt.Scanln(&discard)
return
}
fmt.Printf("Input contained %d", i)
}
Run Code Online (Sandbox Code Playgroud)
然而,似乎应该有一个更优雅的解决方案。特别是在 fmt.Scanln 的情况下,读取在第一个非数字字节之后停止而不是“扫描行”似乎很奇怪。
每次失败后,我都会通过阅读直到行尾来解决此问题。这会清除文本的其余部分。
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
stdin := bufio.NewReader(os.Stdin)
fmt.Println("Please enter an integer: ")
var userI int
for {
_, err := fmt.Fscan(stdin, &userI)
if err == nil {
break
}
stdin.ReadString('\n')
fmt.Println("Sorry, invalid input. Please enter an integer: ")
}
fmt.Println(userI)
}
Run Code Online (Sandbox Code Playgroud)