You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go中fmt.Println覆盖bufio Scanner读取行及切片存储异常问题

问题原因拆解

1. 输出覆盖行的根源

你的文本文件用了**回车符(\r)**代替了标准的换行符(\n,Windows下一般是\r\n)。当fmt.Println输出带\r的内容时,这个符号会把终端光标拽回当前行开头,后面的内容直接覆盖前面的,看起来就像没换行一样。

2. 只存第一个条目的问题

十有八九是你的代码只调用了一次scanner.Scan(),没循环读取所有行。bufio.Scanner的Scan()每次只能读一行(按默认换行符分割),不循环的话自然只能拿到第一行内容;再加上文件里的\r搞事,后面的内容要么被当成同一行的一部分,要么打印时被覆盖,导致你以为只有第一个条目被存下来了。

解决步骤

先搞定换行符问题

给Scanner自定义分割规则,让它能识别\r、\n、\r\n这几种换行方式:

scanner := bufio.NewScanner(file)
// 自定义分割函数,兼容各种换行符
scanner.Split(func(data []byte, atEOF bool) (advance int, token []byte, err error) {
    for i := 0; i < len(data); i++ {
        if data[i] == '\n' || data[i] == '\r' {
            // 处理Windows的\r\n组合
            if i+1 < len(data) && data[i] == '\r' && data[i+1] == '\n' {
                return i+2, data[:i], nil
            }
            return i+1, data[:i], nil
        }
    }
    if atEOF && len(data) > 0 {
        return len(data), data, nil
    }
    return 0, nil, nil
})

再修复只读第一行的问题

必须用循环调用scanner.Scan()遍历所有行,把每行分割后的姓名都追加到切片里:

var names []string
for scanner.Scan() {
    line := scanner.Text()
    fmt.Println(line) // 现在不会再覆盖了
    // 把当前行的姓名分割后批量追加到切片
    names = append(names, strings.Fields(line)...)
}

// 别忘了检查扫描过程中有没有出错
if err := scanner.Err(); err != nil {
    fmt.Println("读文件出问题了:", err)
    return
}

完整修复后的代码

package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

func main() {
	file, err := os.Open("names.txt")
	if err != nil {
		fmt.Println("打开文件失败:", err)
		return
	}
	defer file.Close()

	scanner := bufio.NewScanner(file)
	// 自定义分割函数兼容各种换行符
	scanner.Split(func(data []byte, atEOF bool) (advance int, token []byte, err error) {
		for i := 0; i < len(data); i++ {
			if data[i] == '\n' || data[i] == '\r' {
				if i+1 < len(data) && data[i] == '\r' && data[i+1] == '\n' {
					return i+2, data[:i], nil
				}
				return i+1, data[:i], nil
			}
		}
		if atEOF && len(data) > 0 {
			return len(data), data, nil
		}
		return 0, nil, nil
	})

	var names []string
	for scanner.Scan() {
		line := scanner.Text()
		fmt.Println(line)
		names = append(names, strings.Fields(line)...)
	}

	if err := scanner.Err(); err != nil {
		fmt.Println("扫描文件出错:", err)
		return
	}

	fmt.Println("所有姓名:", names)
}

内容的提问来源于stack exchange,提问作者Pavlo Maistrenko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 00:41:12