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

Go脚本未进入for循环:逐行处理TSV文件异常求助

问题描述

执行一段逐行读取TSV文件并提取内容写入新文件的Go脚本时,发现跳过表头后脚本直接退出,完全没进入循环执行逻辑。脚本代码如下:

func main() {
    inFile := "file.tsv"

    reader, err := os.Open(inFile)
    if err != nil {
        log.Println(err)
    }
    defer reader.Close()

    scanner := bufio.NewScanner(reader)
    scanner.Scan()  // skip header

    for scanner.Scan() {
        row := strings.Split(scanner.Text(), "\t")

        outFileName := fmt.Sprintf("./out_name__%s", row[1])
        writer, err := os.Create(outFileName)
        if err != nil {
            log.Println(err)
            writer.Close()
        }

        writer.Write([]byte(row[2]))
        writer.Close()
    }
}
问题原因
  • 未检查跳过表头的scanner.Scan()返回值:如果目标文件只有表头行,或者第一次scanner.Scan()因读取错误、文件为空等原因返回false,后续循环的scanner.Scan()条件自然不会触发。
  • 未捕获扫描过程中的错误:整个扫描流程没有调用scanner.Err(),如果文件读取时发生IO错误,会导致扫描提前终止,且无法得知具体错误原因。
  • 错误处理逻辑有隐患:创建文件失败时,writer可能为nil,此时调用writer.Close()会直接触发panic,但你的场景中脚本直接退出,核心原因还是扫描环节的问题。
修复方案
  1. 检查跳过表头的扫描结果,避免空文件或表头读取失败直接进入循环
  2. 循环结束后调用scanner.Err()排查潜在IO错误
  3. 修正文件写入的错误处理逻辑,避免对nil的writer执行操作
  4. 增加行格式校验,避免索引越界panic

修改后的代码示例:

func main() {
    inFile := "file.tsv"

    reader, err := os.Open(inFile)
    if err != nil {
        log.Fatal(err) // 文件打开失败直接终止流程
    }
    defer reader.Close()

    scanner := bufio.NewScanner(reader)
    // 跳过表头,先检查扫描是否成功
    if !scanner.Scan() {
        if err := scanner.Err(); err != nil {
            log.Fatalf("读取表头失败: %v", err)
        }
        log.Println("文件为空或仅包含表头行")
        return
    }

    for scanner.Scan() {
        row := strings.Split(scanner.Text(), "\t")
        // 校验行格式,避免索引越界
        if len(row) < 3 {
            log.Println("行格式错误,字段数量不足")
            continue
        }

        outFileName := fmt.Sprintf("./out_name__%s", row[1])
        writer, err := os.Create(outFileName)
        if err != nil {
            log.Printf("创建文件%s失败: %v", outFileName, err)
            continue // 跳过当前行,不执行后续写入操作
        }

        _, err = writer.Write([]byte(row[2]))
        if err != nil {
            log.Printf("写入文件%s失败: %v", outFileName, err)
        }
        writer.Close()
    }

    // 检查扫描全程是否有IO错误
    if err := scanner.Err(); err != nil {
        log.Fatalf("文件扫描失败: %v", err)
    }
}

内容的提问来源于stack exchange,提问作者t.ry

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 23:42:48