Golang中fmt.scan如何处理格式错误的数字
Golang中fmt.scan如何处理格式错误的数字 大家好,
我的代码会请求输入一个数字,然后再请求输入另一个数字。之后,它会按顺序打印这两个数字,一个接一个。
奇怪的是,当我输入的数字中包含其他字符时,会发生一些奇怪的事情。我将在下面展示一些例子。我的问题是,为什么会发生这种情况?为什么完全相同的代码在Windows和Linux上的异常行为会不同?这些例子是在Linux上运行的;在Windows上运行此代码会显示出更奇怪的行为。你需要自己在Windows机器上查看结果。
// 示例1:正常运行 $ go run numbers1.go 输入数字 1: 5 输入数字 2: 7 5 7
// 示例2:第二个数字格式错误 - 这里第二个命令行自动输入了890 $ go run numbers1.go 输入数字 1: 123 输入数字 2: 567q890 123 567 $ 890 bash: 890: command not found… Failed to search for file: Timeout was reached $
// 示例3:第一个数字格式错误 - 这里我只输入了第一个数字,第二个数字自动出现了。 $ go run numbers1.go 输入数字 1: 123q456 输入数字 2: 123 456 $
// 示例4:第一个数字格式错误 - 这里我只输入了第一个数字,第二个数字自动出现了。在“Command not found…”之后,我按了几次回车键,但没有任何反应,所以我按了“CTRL-C”。 $ go run numbers1.go 输入数字 1: 123qwe456 输入数字 2: 123 0 $ e456 bash: e456: command not found…
^C $
package main
import (
"fmt"
)
func main() {
var num1 int64
var num2 int64
fmt.Print("Enter number 1: ")
fmt.Scan(&num1)
fmt.Print("Enter number 2: ")
fmt.Scan(&num2)
fmt.Println(num1)
fmt.Println(num2)
}
更多关于Golang中fmt.scan如何处理格式错误的数字的实战教程也可以访问 https://www.itying.com/category-94-b0.html
你好,感谢你的回复。
对于第一个数字,你在 printf() 这一行捕获了第一个错误,例如 _, err := fmt.Print("Enter number 1: ")
但对于第二个数字,你却在 fmt.Scan() 这一行捕获错误,_, err = fmt.Scan(&num2)
这是为什么呢? 另外,你是否知道这种奇怪的行为在内部是如何发生的?
更多关于Golang中fmt.scan如何处理格式错误的数字的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
如果左侧有新的标识符,则必须使用赋值运算符 :=。由于 err 在此处是首次声明,因此必须使用 :=。之后,将新值赋给一个已存在的标识符(err)。对于这种情况,必须使用运算符 =。
请查阅 https://golang.org/ref/spec#Short_variable_declarations 和 https://golang.org/ref/spec#Assignments。
我不清楚为什么忽略错误会导致观察到的行为。
永远不要忽略错误。fmt.Scan 的函数签名是:
func Scan(a ...interface{}) (n int, err error)
请务必处理这个错误!
package main
import (
"fmt"
"log"
)
func main() {
var num1 int64
var num2 int64
_, err := fmt.Print("Enter number 1: ")
fmt.Scan(&num1)
if err != nil {
log.Panic(err)
}
fmt.Print("Enter number 2: ")
_, err = fmt.Scan(&num2)
if err != nil {
log.Panic(err)
}
fmt.Println(num1)
fmt.Println(num2)
}
如果你使用无效的输入运行此代码,一切正常:
❯ go run forum.go
Enter number 1: 2
Enter number 2: 3
2
3
❯ go run forum.go
Enter number 1: a
Enter number 2: b
2020/08/21 07:51:08 expected integer
panic: expected integer
goroutine 1 [running]:
log.Panic(0xc00006cf40, 0x1, 0x1)
/usr/local/Cellar/go/1.13.1/libexec/src/log/log.go:338 +0xac
main.main()
/tmp/forum.go:22 +0x2a9
exit status 2
fmt.Scan在遇到格式错误的数字时,会根据空格和换行符进行输入流的分割处理,未成功解析的部分会留在输入缓冲区中,影响后续的读取。Windows和Linux的终端输入处理机制不同,可能导致行为差异。以下是具体分析和改进方案:
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
fmt.Print("Enter number 1: ")
text1, _ := reader.ReadString('\n')
num1, err1 := strconv.ParseInt(strings.TrimSpace(text1), 10, 64)
if err1 != nil {
fmt.Println("Invalid input for number 1, using default 0")
num1 = 0
}
fmt.Print("Enter number 2: ")
text2, _ := reader.ReadString('\n')
num2, err2 := strconv.ParseInt(strings.TrimSpace(text2), 10, 64)
if err2 != nil {
fmt.Println("Invalid input for number 2, using default 0")
num2 = 0
}
fmt.Println(num1)
fmt.Println(num2)
}
对于原代码的异常行为解释:
- 当输入
567q890时,fmt.Scan解析到q停止,将567存入变量,剩余的890留在缓冲区 - 第二个
fmt.Scan直接从缓冲区读取890,跳过用户输入 - 缓冲区清空后,
890被shell当作命令执行,出现command not found
跨平台差异原因:
- Windows和Linux的换行符不同(
\r\nvs\n) - 终端输入缓冲区的处理机制存在系统级差异
- 建议使用
bufio进行行读取,避免平台依赖问题

