
Go 的 fmt.Scanln 默认以空格和换行符为分隔符,仅读取首个单词;若需读取含空格的完整一行(如文件内容、句子),应使用 bufio.NewReader(os.Stdin) 配合 ReadString('\n') 或 ReadLine()。
go 的 `fmt.scanln` 默认以空格和换行符为分隔符,仅读取首个单词;若需读取含空格的完整一行(如文件内容、句子),应使用 `bufio.newreader(os.stdin)` 配合 `readstring('\n')` 或 `readline()`。
在 Go 中,fmt.Scanln 并非“读取一行”,而是按空白字符(空格、制表符、换行符)分割输入,并只提取第一个非空字段。这就是为什么输入 "Hello World" 时,程序只捕获 "Hello" ——Scanln 在遇到空格后即停止扫描,后续内容被丢弃或滞留在输入缓冲区中,导致逻辑异常。
要真正读取用户输入的整行字符串(包括空格、制表符等),必须使用 bufio.Reader。以下是推荐的两种安全方式:
✅ 方式一:ReadString('\n')(推荐,简洁清晰)
import "bufio"
reader := bufio.NewReader(os.Stdin)
line, err := reader.ReadString('\n')
if err != nil {
panic(err)
}
// 去除末尾的换行符 \n(ReadString 会将其包含在结果中)
line = strings.TrimSpace(line) // 或 strings.TrimSuffix(line, "\n")
✅ 方式二:ReadLine()(更底层,需手动处理换行与续读)
line, isPrefix, err := reader.ReadLine()
if err != nil {
panic(err)
}
if isPrefix { /* 处理超长行被截断的情况 */ }
s := string(line) // 注意:不包含换行符
⚠️ 注意事项:
- ReadString('\n') 返回的字符串包含末尾的 \n,务必用 strings.TrimSpace() 或 strings.TrimSuffix(line, "\n") 清理,否则写入文件会出现多余空行;
- 不要在同一程序中混用 fmt.Scanln 和 bufio.Reader——前者会残留未读字节,干扰后者行为;
- ioutil.ReadFile 已在 Go 1.16+ 中被标记为废弃,建议改用 os.ReadFile(功能相同,更轻量)。
✅ 修正后的完整示例(关键部分已优化)
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
fmt.Print("请输入文件名(不带扩展名): ")
fileName, _ := reader.ReadString('\n')
fileName = strings.TrimSpace(fileName) + ".txt"
file, err := os.Create(fileName)
check(err)
defer file.Close()
fmt.Printf("文件名已设为 %s,请输入内容: ", fileName)
content, _ := reader.ReadString('\n')
content = strings.TrimSpace(content)
if len(content) == 0 {
panic("输入不能为空")
}
_, err = file.WriteString(content)
check(err)
// 重新读取验证
data, _ := os.ReadFile(fileName)
fmt.Println("*******************FILE*********************")
fmt.Println(string(data))
}
func check(e error) {
if e != nil {
panic(e)
}
}
通过 bufio.Reader 替代 fmt.Scanln,即可可靠读取含空格、制表符甚至中文的整行输入,彻底解决“只读到第一个单词”的问题。这是 Go 标准库中处理交互式文本输入的标准实践。











