go - 如何模拟调用 io.Copy 的函数

标签 go

尝试模拟以下函数。它基本上从 S3 ( io.ReadCloser ) 获取一个对象并将其写入执行 os.Open() 的文件中。 d 较早 ( io.WriteCloser )。

package main

import (
    "io"

    log "github.com/sirupsen/logrus"
)

func writeFile(destination io.WriteCloser, source io.ReadCloser) error {
    defer destination.Close()
    defer source.Close()
    _, err := io.Copy(destination, source)
    if err != nil {
        log.WithFields(log.Fields{"desc": "unable to copy contents from s3 to blahblah"}).Error(err)
        return err
    }
    return nil
}

我认为我已经非常接近了,但目前我的测试挂起并且从未错误/成功...我还意识到我可以通过 os.Stdout到了目的地,但仍然遇到同样的问题。 io.Copy 内发生了一些事情。我想这是因为我试图将空数据复制到什么都没有?

package main

import (
    "errors"
    "io"
    "reflect"
    "testing"
)

type mockReadCloser struct {}

func (m mockReadCloser) Read(p []byte) (int, error) { return 0, nil }
func (m mockReadCloser) Close() error               { return nil }

type mockWriteCloser struct{}

func (m mockWriteCloser) Close() error                      { return nil }
func (m mockWriteCloser) Write(b []byte) (n int, err error) { return 0, nil }

func Test_writeFile(t *testing.T) {
    type args struct {
        destination io.WriteCloser
        source      io.ReadCloser
    }
    tests := []struct {
        name    string
        args    args
        wantErr bool
    }{
        {
            name: "",
            args: args{
                destination: &mockWriteCloser{},
                source:      &mockReadCloser{},
            },
            wantErr: false,
        },
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            if err := writeFile(tt.args.destination, tt.args.source); (err != nil) != tt.wantErr {
                t.Errorf("writeFile() error = %v, wantErr %v", err, tt.wantErr)
            }
        })
    }
}

最佳答案

因为io.Copy直到 EOF 或错误才返回。

Copy copies from src to dst until either EOF is reached on src or an error occurs. It returns the number of bytes copied and the first error encountered while copying, if any.

A successful Copy returns err == nil, not err == EOF. Because Copy is defined to read from src until EOF, it does not treat an EOF from Read as an error to be reported.

因此,如果您从 mockReadCloser.Read 返回 EOF,它就不会再挂起。

func (m mockReadCloser) Read(p []byte) (int, error) { return 0, io.EOF }

这是因为 Read 被重复调用,直到没有更多内容可供读取 (EOF)。

for {
    nr, er := src.Read(buf)
    ...
}

关于go - 如何模拟调用 io.Copy 的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72669429/

相关文章:

go - 为什么计数器不通过方法增加函数参数

go - 嵌入目录中的 index.html 在哪里?

mongodb - 使用 session 的官方 mongo-go-driver

go - 从 Tcl 脚本调用 golang 函数

包含斜杠和星号作为常量的正则表达式

go - golang 中原始值的 typedef 是否等效?

function - 在 Golang 中使用另一个函数返回一个值?

go - Golang "func (t *SomeType) myFuncName(param1, param2)"语法是什么意思

go - 属于关联 Golang Gorm 未找到具有显式 ForeignKey

go - 无法通过 github API 获取所有存储库