go - Scanf 值在终端中作为命令执行
问题描述
我有一个简单的 go 程序,可以将英里转换为公里:
const kmInMile = 1.609344
func main() {
var miles float64
fmt.Print("Enter miles: ")
fmt.Scanf("%f", &miles)
fmt.Println(miles)
km := kmInMile * miles
fmt.Println(miles, "miles =", km, "km")
}
如果我将“lls”作为输入传递给scanf:
Enter miles: lls
输出是:
0
0 miles = 0 km
alexandrkrivosheev$ ls
hello main.go
所以输入的第一个字符被采用,所有其他字符都作为命令执行。为什么会发生这种情况,我该如何预防?
完整的终端会话:
alexandrkrivosheev$ ./hello
Enter miles: lls
0
0 miles = 0 km
alexandrkrivosheev$ ls
hello main.go
alexandrkrivosheev$
解决方案
使用“plain fmt.Scanf”时,输入必须与预期格式匹配,即在您的情况下,它必须是有效的浮点数。如果不是,则中止扫描,其余输入保留在控制台的输入缓冲区中,在程序退出后作为下一个命令执行。
要解决此问题,请将标准输入包装到bufio.Reader
or中bufio.Scanner
:
func main() {
var miles float64
fmt.Print("Enter miles: ")
//
reader := bufio.NewReader(os.Stdin)
val, err := reader.ReadString('\n')
if err != nil {
fmt.Println(err)
return
}
if _, err = fmt.Sscanf(val, "%f", &miles); err != nil {
fmt.Println(val, err)
return
}
fmt.Println(miles)
km := kmInMile * miles
fmt.Println(miles, "miles =", km, "km")
}
这样您就可以从输入中消耗整行并单独处理它。
推荐阅读
- google-apps-script - 驱动器选择器小部件在以开发人员身份运行模式下不起作用
- reactjs - 我应该在组件生命周期中何时从 URL 获取查询参数?
- windows - 运行 7zip 设置后,用于静默安装 7zip 的批处理脚本不会继续
- javascript - 未通过php电子邮件接收联系信息
- fortran - 尝试在工作目录之外创建文件时“没有这样的文件或目录”
- kotlin - kotlin coroutines - use main thread in run blocking
- javascript - 动态创建的文本字段的访问值
- android - Facebook android 应用丢弃通过 Intent 传递的#hashtag。但它适用于iOS
- android - Flutter - 如何仅在列表视图中显示所选项目
- c++ - 关于 SFINAE 的函数和结构之间的差异