
go中使用bufio.readstring读取输入时会保留末尾换行符,导致后续strings.split产生的最后一个字段包含"\n",使strconv.parseint解析失败并返回0——这是忽略错误检查引发的典型问题。
go中使用bufio.readstring读取输入时会保留末尾换行符,导致后续strings.split产生的最后一个字段包含"\n",使strconv.parseint解析失败并返回0——这是忽略错误检查引发的典型问题。
在Go语言中,bufio.Reader.ReadString('\n') 的行为是读取直到第一个换行符(包括该换行符本身),因此输入 "5 25 125\n" 经 strings.Split(line, " ") 后实际得到的是:
splitted = []string{"5", "25", "125\n"}注意:splitted[2] 并非 "125",而是 "125\n"。而 strconv.ParseInt("125\n", 0, 64) 无法解析含非数字字符的字符串,立即返回 (0, error) ——由于你忽略了错误(用 _ 丢弃),程序继续使用默认值 0,造成“意外为0”的现象。
✅ 正确做法是:始终检查错误,并预处理输入字符串。推荐方案如下:
✅ 方案一:使用 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 {
panic(err) // 或妥善处理IO错误
}
// 去除行尾换行符及可能的空格
line = strings.TrimSpace(line)
splitted := strings.Split(line, " ")
if len(splitted) < 3 {
panic("insufficient input fields")
}
N, err := strconv.ParseInt(splitted[0], 10, 64)
if err != nil {
panic(fmt.Sprintf("failed to parse N: %v", err))
}
P, err := strconv.ParseInt(splitted[1], 10, 64)
if err != nil {
panic(fmt.Sprintf("failed to parse P: %v", err))
}
Q, err := strconv.ParseInt(splitted[2], 10, 64)
if err != nil {
panic(fmt.Sprintf("failed to parse Q: %v", err))
}
fmt.Println(N, P, Q) // 输出:5 25 125
}✅ 方案二:使用 fmt.Sscanf(更简洁、更健壮)
var N, P, Q int64
_, err := fmt.Sscanf(line, "%d %d %d", &N, &P, &Q)
if err != nil {
panic(fmt.Sprintf("parse error: %v", err))
}⚠️ 关键注意事项:
-
永远不要忽略
strconv系列函数的返回错误:ParseInt、Atoi等在失败时均返回0+error,_丢弃错误等于主动引入静默故障; -
明确进制参数:
strconv.ParseInt(s, 0, 64)中0表示自动推断进制(支持0x/0o/0b前缀),若输入纯十进制数字,建议显式写10提高可读性与安全性; -
验证切片长度:
splitted[2]可能越界(如输入只有两个数),务必先检查len(splitted) >= 3; - 替代
ReadString的更安全选择:bufio.Scanner(默认以\n分割且自动去除换行符):scanner := bufio.NewScanner(os.Stdin) if scanner.Scan() { line := scanner.Text() // ← 自动不含 '\n' // 后续处理同上 }
遵循以上实践,即可彻底避免因残留换行符和忽略错误导致的“解析结果意外为0”问题。
立即学习“go语言免费学习笔记(深入)”;


















