
在 Go 中使用 bufio.NewReader.ReadString() 读取用户输入时,返回的字符串默认包含换行符 \n,直接与 "hi" 比较会失败;需通过 strings.TrimRight()、reader.ReadLine() 或 bufio.Scanner 等方式去除尾部换行符后再判断。
在 go 中使用 `bufio.newreader.readstring()` 读取用户输入时,返回的字符串默认包含换行符 `\n`,直接与 `"hi"` 比较会失败;需通过 `strings.trimright()`、`reader.readline()` 或 `bufio.scanner` 等方式去除尾部换行符后再判断。
Go 的标准库在处理标准输入时行为严谨但易被初学者忽略一个关键细节:ReadString('\n') 和 ReadBytes('\n') 返回的内容包含终止符本身。这意味着当你键入 hi 并按下回车,实际读到的是 "hi\n"(长度为 3),而非预期的 "hi"(长度为 2),导致 if text == "hi" 永远为 false。
以下是几种推荐的修复方案,按简洁性与实用性排序:
✅ 推荐方案:使用 bufio.Scanner(最简洁、最惯用)
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
fmt.Println("Simple Shell")
fmt.Println("---------------------")
for {
fmt.Print("-> ")
if !scanner.Scan() {
break // 处理 EOF 或错误
}
text := scanner.Text() // 自动去除换行符,返回 clean 字符串
if text == "hi" {
fmt.Println("hiii")
} else if text == "quit" {
fmt.Println("Goodbye!")
break
}
}
}Scanner.Text() 内部已自动剥离 \r\n 或 \n,无需手动处理,且支持错误检测(scanner.Err() 可进一步检查 I/O 错误)。
⚠️ 替代方案:strings.TrimRight 清洗 ReadString 结果
import "strings"
// … 在循环中 …
text, err := reader.ReadString('\n')
if err != nil {
fmt.Fprintln(os.Stderr, "读取输入失败:", err)
continue
}
text = strings.TrimRight(text, "\r\n") // 同时兼容 Windows/Linux 换行
if text == "hi" {
fmt.Println("hiii")
}注意:必须显式检查 err,且建议同时去除 \r\n(Windows)和 \n(Unix),避免跨平台问题。
? 不推荐但需理解:ReadLine(需类型转换)
text, isPrefix, err := reader.ReadLine()
if err != nil { /* handle */ }
if !isPrefix && string(text) == "hi" { // isPrefix 为 true 表示行过长被截断
fmt.Println("hiii")
}ReadLine 返回 []byte,且需额外判断 isPrefix,对简单场景略显冗余。
? 关键注意事项
-
永远不要忽略错误:
ReadString、Scan()等函数可能返回io.EOF或其他错误,生产代码中应妥善处理; -
避免裸
_忽略错误:原代码中_ := reader.ReadString('\n')会掩盖输入中断、管道关闭等问题; -
字符串比较区分大小写:若需忽略大小写,可用
strings.EqualFold(text, "hi"); -
性能考量:
Scanner默认缓冲 64KB,对命令行交互完全足够;如需超长行或二进制输入,再考虑ReadBytes+bytes.TrimRight。
综上,bufio.Scanner 是 Go 中读取用户逐行输入的首选方式——语义清晰、安全可靠、代码简洁。掌握这一模式,可避免绝大多数与换行符相关的逻辑陷阱。

















