
Go 中使用 bufio.ReadString 读取输入时会保留末尾的换行符(\n),导致后续 strconv.ParseInt 解析失败并返回 0 和错误,需先用 strings.TrimSpace 清理空白字符。
go 中使用 `bufio.readstring` 读取输入时会保留末尾的换行符(`\n`),导致后续 `strconv.parseint` 解析失败并返回 0 和错误,需先用 `strings.trimspace` 清理空白字符。
在 Go 中进行字符串到整数的解析时,一个常见却容易被忽视的问题是:输入字符串中隐含的不可见字符(尤其是换行符 \n)会导致 strconv.ParseInt 解析失败,返回默认值 0 和非 nil 错误。这正是你遇到 "5 25 125" 输入却得到 5 25 0 输出的根本原因。
问题根源在于 bufio.NewReader(os.Stdin).ReadString('\n') 的行为:它会完整读取包括换行符在内的所有内容。例如,输入 "5 25 125\n" 时,line 的值实际为 "5 25 125\n"。调用 strings.Split(line, " ") 后,第三个元素 splitted[2] 并非 "125",而是 "125\n"。而 strconv.ParseInt("125\n", 0, 64) 无法将带换行符的字符串解析为有效整数,因此返回 (0, error) —— 这正是 Q 变成 0 的原因。
✅ 正确做法是:在解析前清除每段子字符串两端的空白字符(包括 \n, \r, \t, 空格等)。推荐使用 strings.TrimSpace:
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
line, err := reader.ReadString('\n')
if err != nil {
fmt.Fprintln(os.Stderr, "读取输入失败:", err)
return
}
splitted := strings.Fields(line) // 更健壮:按任意空白分割,自动跳过空字段
if len(splitted) < 3 {
fmt.Fprintln(os.Stderr, "输入格式错误:至少需要三个整数")
return
}
// 安全解析:先 TrimSpace,再检查错误
N, err := strconv.ParseInt(strings.TrimSpace(splitted[0]), 10, 64)
if err != nil {
fmt.Fprintln(os.Stderr, "解析 N 失败:", err)
return
}
P, err := strconv.ParseInt(strings.TrimSpace(splitted[1]), 10, 64)
if err != nil {
fmt.Fprintln(os.Stderr, "解析 P 失败:", err)
return
}
Q, err := strconv.ParseInt(strings.TrimSpace(splitted[2]), 10, 64)
if err != nil {
fmt.Fprintln(os.Stderr, "解析 Q 失败:", err)
return
}
fmt.Println(N, P, Q) // 输出:5 25 125
}? 关键改进说明:
- 使用
strings.Fields(line)替代strings.Split(line, " "):它按任意空白(空格、制表符、换行等)分割,并自动忽略空字符串,避免因多余空格导致splitted长度异常; -
绝不忽略
strconv.ParseInt的错误返回:Go 的错误处理是显式契约,忽略err是导致静默0值的元凶; - 明确指定进制(如
10)而非0:0表示自动推断(支持0x/0o/0b前缀),但用户输入通常为十进制,显式写10更安全、可读; - 添加基础输入校验(如长度检查)和错误提示,提升程序鲁棒性。
? 小结:在 Go 中处理用户输入时,永远假设字符串“不干净”。TrimSpace 是解析前的必要预处理步骤;而永远检查并响应错误值,而非依赖默认返回值,这是写出可靠命令行工具的核心习惯。

















