go - 如何正确检查 io.Reader 是否为零?

标签 go pointers interface null

如果您创建一个 bytes.Buffer 类型的变量(未初始化)并将其分配给 io.Reader 类型的字段,则在检查 io 后.Reader for nil 会出现错误:内存地址无效或 nil 指针取消引用。如何正确检查以避免此类错误?

Playground

package main

import (
    "bytes"
    "io"
    "io/ioutil"
)

type Request struct {
    Body io.Reader
}

func main() {
    var data *bytes.Buffer

    request := &Request{
        Body: data,
    }

    if request.Body != nil {
        ioutil.ReadAll(request.Body) // panic: runtime error: invalid memory address or nil pointer dereference
    }
}

最佳答案

检查是否有 io.Reader (或任何其他接口(interface))值为 nil,您只需将其与 nil 进行比较即可。

nil io.Reader是否是有意义的实现,这是另一个问题。

例如这个实现有意义吗?

type panicReader struct{}

func (panicReader) Read(p []byte) (int, error) {
    panic("foo")
}

panicReader 当然实现了 io.Reader,但每当你调用它的 Read() 方法时,它总是会出现 panic 。

bytes.Buffer 。指向它的指针实现了io.Reader。但打电话Buffer.Read()nil *bytes.Buffer 指针值上会发生 panic 。但这并不是因为您无法在 nil 指针接收器上调用方法,而是因为 bytes.Buffer.Read() 的实现尝试取消引用指针接收器,并且此取消引用操作是导致 panic 的原因:

// Excerpt from bytes.Buffer.Read implementation 
func (b *Buffer) Read(p []byte) (n int, err error) {
    b.lastRead = opInvalid
    if b.empty() {
    // ...
}

您(目前还不能)在此做出一般性结论。请参阅此 io.Reader 实现:

type myBuffer struct{}

var count int

func (*myBuffer) Read(p []byte) (int, error) {
    if len(p) > 0 {
        count++
        if count >= 10 {
            return 0, io.EOF
        }
        p[0] = 'a'
        return 1, nil
    }
    return 0, nil
}

*myBuffer 实现了 io.Reader,其 Read() 方法不使用指针接收器值。这是什么意思?您可以nil *myBuffer值调用Read():

var data *myBuffer

request := &Request{
    Body: data,
}

if request.Body != nil {
    data, err := ioutil.ReadAll(request.Body)
    fmt.Println(string(data), err)
}

这将输出(在 Go Playground 上尝试):

aaaaaaaaa <nil>

所以结论是这样的:通常具有带有指针接收器的方法的类型需要非nil指针,因为它们使用指向对象(在 bytes.Buffer 的情况下,它们使用指向结构的字段)。要使用此类类型(为了对已实现的接口(interface)进行有意义的实现),您通常需要一个非 nil 指针值才能使方法“工作”。然而,正如上面的 myBuffer 实现所示,这并不总是必需的。您的工作是始终阅读所使用类型和方法的文档,以避免此类误用(例如尝试使用 nil *bytes.Buffer)。

查看相关问题:

Hiding nil values, understanding why Go fails here

Go reflection with interface embedded in struct - how to detect "real" functions?

关于go - 如何正确检查 io.Reader 是否为零?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72032762/

相关文章:

创建一个链接列表,以升序存储项目或按该顺序打印

c# - 进入/调试接口(interface)实现者

json - Go json.Marshal 无法获得单个反斜杠

去生成 : stringer: invalid operation: has no field or method String

c - C语言中的复杂指针语句

C 指针差异 Char Int

python - 包装一个接受指针数组的函数

c++ - 隐藏容器的类的更好接口(interface)

go - golang中的FFmpeg I-P帧命令

go - GO编译WASM导出函数