要判断io.Reader
(或任何其他接口)值是否为nil
,只需将其与nil
进行比较.
非nil
io.Reader
是否是一个有意义的实现,这是另一个问题.
例如,这种实施有意义吗?
type panicReader struct{}
func (panicReader) Read(p []byte) (int, error) {
panic("foo")
}
panicReader
当然实现io.Reader
,但无论何时调用它的Read()
方法,它都会惊慌失措.
有bytes.Buffer
个.指向它的指针实现了io.Reader
.但在nil
*bytes.Buffer
指针值上调用Buffer.Read()
会引起panic .但这并不是因为你不能在nil
个指针接收器上调用方法,而是因为bytes.Buffer.Read()
的实现试图go 引用指针接收器,而这种go 引用操作正是导致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上try ):
aaaaaaaaa <nil>
所以结论是:usually种类型的方法带有指针接收器,它们需要一个非nil
指针,因为它们使用pointed对象(在bytes.Buffer
种情况下,它们使用指向 struct 的字段).为了使用这些类型(为了实现有意义的接口实现),您通常需要一个非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?