警惕:golang中的一个接口包括一个空指针并非nil

问题代码:

Update 2017.2.23 See: https://golang.org/doc/faq#nil_error

package main

import (
    "bytes"
    "fmt"
    "io"
)

func main() {
    var buf *bytes.Buffer  // 注意此处为指针类型 impl interface io.Writer

    fmt.Println(fmt.Sprintf("%V", buf))

    test(buf)
}

func test(out io.Writer) {
    if out != nil {
        out.Write([]byte("done"))
    }
}

以上程序的运行一定会引起panic,尽管在 test 函数中进行了 if out != nil 。 原因在于 interfacenil 判断的特殊性,因为 interface 的结构包括两部分 typedata, 我们定义的 var buf *bytes.Buffer,声明了一个接口包括一个空指针【但是non-nil】 bytes.Buffer类型空指针,该指针的数据为nil,结构大体如下:

var buffer *bytes.Buffer:

type:  *bytes.Buffer
data:  nil

但是在test函数中的传递的接口类型为 out io.Writer, 因此 if out != nil 中的 nil 结构如下:

    type:  nil
    data:  nil

修改方式:

    func main() {
    var buf io.Writer  // *bytes.Buffer  // impl interface io.Writer

    fmt.Println(fmt.Sprintf("%V", buf))

    test(buf)
}

因为 var buf io.Writer这句话将var声明成了一个真正的 nil interface。

    type:  nil
    data:  nil

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注