go io: 隐式复制要求WriterTo和ReaderFrom不返回io.EOF,

bfrts1fy  于 4个月前  发布在  Go
关注(0)|答案(5)|浏览(63)

你正在使用的Go版本是什么( go version )?

$ go version
go version go1.14.15 linux/amd64

这个问题在最新版本的发布中是否重现?

是的。

你正在使用什么操作系统和处理器架构( go env )?

go env 输出

$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/cyphar/.cache/go-build"
GOENV="/home/cyphar/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/cyphar/.local"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/lib64/go/1.14"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/lib64/go/1.14/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build440126677=/tmp/go-build -gno-record-gcc-switches"

你做了什么?

https://play.golang.org/p/6dFx2mL7f5r

package main

import (
	"fmt"
	"io"
	"io/ioutil"
)

type dummyReader struct {}

func (r dummyReader) Read(p []byte) (n int, err error) {
	return 0, io.EOF
}

type dummyWriteTo struct {
	dummyReader
}

func (r dummyWriteTo) WriteTo(w io.Writer) (n int64, err error) {
	return 0, io.EOF
}

func main() {
	n, err := io.Copy(ioutil.Discard, dummyReader{})
	fmt.Printf("io.Copy using io.Reader -- n=%v, err=%v\n", n, err)
	
	n, err = io.Copy(ioutil.Discard, dummyWriteTo{})
	fmt.Printf("io.Copy using io.WriterTo -- n=%v, err=%v\n", n, err)
}

主要问题是,如果你有一个实现了返回 io.EOFio.Reader,那么 io.Copy 会盲目地转发这个错误。 klauspost/pgzip#38 是一个犯了这个错误的例子,我在 opencontainers/umoci#360 中遇到了这个问题。
同样的事情也发生在从 ReadFrom 返回 io.EOF (这有点奇怪,但如果你不在 io.Copy 的实现中使用 io.ReaderFrom,你可能会不小心这样做)。
看起来这要么是:

  • 一个文档问题,因为据我所知, io.WriterToio.ReaderFrom 的文档没有提到不应该从这些方法中返回 io.EOF。措辞上确实暗示了不应该返回 io.EOF,但我认为这应该更加明确,因为任何不使用 io.Copy 内部实现的 WriteTo 实现都必须显式处理这个问题,并应该被警告这种情况。
  • io.Copy (以及可能与 io.WriterToio.ReaderFrom 相关的相关 stdlib 用户)的一个bug,因为当它由 io.EOF 返回时, x20n20会被处理。

你期望看到什么?

x22b22
或者文档提到不应该从 x23n23 返回 x24n24。

你看到了什么?

x25b25

rta7y2nd

rta7y2nd1#

我认为这是一个文档问题。我无法看到任何理由为什么WriteToReadFrom应该返回io.EOF

xhv8bpkk

xhv8bpkk2#

@ianlancetaylor 我做了一份PR,你能帮忙看一下吗?谢谢!

n3h0vuf2

n3h0vuf23#

https://golang.org/cl/294709提到了这个问题:fix: io/copy document. fix #44411

kxe2p93d

kxe2p93d4#

我无法看到任何理由为什么WriteTo或ReadFrom应该返回io.EOF。如果你不使用io.Copy内部,而是使用其他一些I/O方法,那么你可能会意外地得到这个结果。但是,如果语义基本上是“更高效的io.Copy”,那么我同意它永远不应该返回io.EOF。谢谢。

z2acfund

z2acfund5#

https://golang.org/cl/294769提到了这个问题:io: unify EOF documentation for ReadFrom and WriteTo

相关问题