猿问

如何正确检查 io.Reader 是否为 nil?

如果你创建一个 type 变量bytes.Buffer(没有初始化)并将它赋给一个 type 字段io.Reader,那么在检查io.Readernil 之后会出现错误:invalid memory address or nil pointer dereference。如何正确检查以避免此类错误?

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

    }

}


慕无忌1623718
浏览 106回答 1
1回答

GCT1015

要检查一个io.Reader(或任何其他接口)值是否为nil,您只需将它与 进行比较nil。非nil io.Reader- 是否是有意义的实现,这是另一个问题。例如,这个实现有意义吗?type panicReader struct{}func (panicReader) Read(p []byte) (int, error) {&nbsp; &nbsp; panic("foo")}panicReader当然 implements io.Reader,但是每当你调用它的Read()方法时,它总是会 panic。有bytes.Buffer。指向它的指针 implements io.Reader。但是调用指针值会出现恐慌Buffer.Read()。nil *bytes.Buffer但这不是因为您不能在nil指针接收器上调用方法,而是因为 的实现bytes.Buffer.Read()试图取消引用指针接收器,而这种取消引用操作是导致恐慌的原因:// Excerpt from bytes.Buffer.Read implementation&nbsp;func (b *Buffer) Read(p []byte) (n int, err error) {&nbsp; &nbsp; b.lastRead = opInvalid&nbsp; &nbsp; if b.empty() {&nbsp; &nbsp; // ...}您不能在这里做出一般性结论(目前)。看到这个io.Reader实现:type myBuffer struct{}var count intfunc (*myBuffer) Read(p []byte) (int, error) {&nbsp; &nbsp; if len(p) > 0 {&nbsp; &nbsp; &nbsp; &nbsp; count++&nbsp; &nbsp; &nbsp; &nbsp; if count >= 10 {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return 0, io.EOF&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; p[0] = 'a'&nbsp; &nbsp; &nbsp; &nbsp; return 1, nil&nbsp; &nbsp; }&nbsp; &nbsp; return 0, nil}*myBufferimplements io.Reader,它的Read()方法不使用指针接收器值。这是什么意思?您可以调用Read()一个nil *myBuffer值:var data *myBufferrequest := &Request{&nbsp; &nbsp; Body: data,}if request.Body != nil {&nbsp; &nbsp; data, err := ioutil.ReadAll(request.Body)&nbsp; &nbsp; fmt.Println(string(data), err)}这将输出(在Go Playground上尝试):aaaaaaaaa <nil>所以结论是这样的:通常具有指针接收器方法的类型需要非nil指针,因为它们使用指向对象(如果bytes.Buffer它们使用指向结构的字段)。要使用此类类型(对已实现的接口进行有意义的实现),您通常需要一个非nil指针值来使方法“工作”。myBuffer然而,正如上面的实现所示,这并不总是一个要求。始终阅读所用类型和方法的文档以避免此类误用(例如尝试使用 a nil *bytes.Buffer)是您的工作。
随时随地看视频慕课网APP

相关分类

Go
我要回答