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

Go中io.Copy无法在os.File类型间复制数据问题咨询

问题根因

你遇到的问题核心是文件偏移量位置错误:

  • 调用os.Create()创建的文件,打开后默认偏移量在文件开头
  • 执行file1.WriteString("Some test data")写入14字节内容后,file1的当前偏移量会移动到14字节的位置(也就是内容末尾)
  • io.Copy(dst, src)的逻辑是从src的当前偏移量开始读取内容,直到遇到EOF,此时src(file1)的偏移量已经在末尾,自然读不到任何内容,所以返回写入0字节,也不会抛出错误,因为EOF属于读取结束的正常状态
  • 你调用readFile能读到file1的内容,是因为ioutil.ReadFile内部会重新打开目标文件,新打开的文件偏移量默认在开头,所以可以读到完整内容。
修复方案

在执行io.Copy之前,将file1的偏移量重置到文件开头即可,调用Seek方法:

// 放在io.Copy之前执行
_, err = file1.Seek(0, io.SeekStart)
if err != nil {
    log.Fatal(err)
}

修改后完整代码如下:

package main

import (
    "io"
    "io/ioutil"
    "log"
    "os"
)

func main() {

    file1, err := os.Create("file1")
    if err != nil {
        log.Fatal(err)
    }
    file1.WriteString("Some test data")
    defer file1.Close()
    defer os.Remove(file1.Name())

    log.Println("File1 Data : ", readFile(file1.Name()))

    file2, err := os.Create("file2")
    if err != nil {
        log.Fatal(err)
    }
    defer file2.Close()
    defer os.Remove(file2.Name())

    // 新增:重置file1的偏移量到开头
    _, err = file1.Seek(0, io.SeekStart)
    if err != nil {
        log.Fatal(err)
    }

    w, err := io.Copy(file2, file1)
    if err != nil {
        log.Fatal(err)
    }

    log.Println("Copied", w)

    log.Println("File2 Data : ", readFile(file2.Name()))
}

func readFile(fname string) string {
    data, err := ioutil.ReadFile(fname)
    if err != nil {
        log.Fatal(err)
    }

    return string(data)
}

修改后运行输出如下:

2009/11/10 23:00:00 File1 Data :  Some test data
2009/11/10 23:00:00 Copied 14
2009/11/10 23:00:00 File2 Data :  Some test data

补充说明:如果你的场景中写入file1后还有其他操作,不方便直接Seek,也可以选择关闭file1后重新以只读模式打开,再传入io.Copy使用,效果一致。

内容的提问来源于stack exchange,提问作者akshay khairmode

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 13:54:04