资深Go程序员也困惑过的陷阱(”含有空指针的非空接口“)!!!

66 阅读1分钟

先来看一个例子:

package main

import "bytes"
import "io"

func write(o io.Writer, s string) {
	if o != nil {
		o.Write([]byte(s))
	}
}

func main() {
	var buf *bytes.Buffer

	write(buf, "Hello World!")
}

执行上述代码,发现程序崩溃了:

Screenshot 2025-03-03 at 20.36.45.png

程序触发了“空指针解引用(nil pointer dereference)”的错误。进一步分析错误可知,表达式o != nil返回非预期值true,导致程序出现异常。

🤔为什么呢?

Go中,接口本质上包含两个部分:

  • 动态类型:接口实际存储的类型。
  • 动态值:接口实际存储的值。

在上述的例子中,当main函数调用write函数时,它把一个类型为*bytes.Buffer的空指针赋值给了o参数。所以o的动态值为nil,动态类型为*bytes.Buffer,如下图所示:

image.png

在调用o.Write([]byte(s))时,它实际上等效于(*buf).Write([]byte(s)),即我们对一个空指针(buf的初始值默认为nil)解引用,引发程序panic

PS:也做了一回标题党!果咩纳塞~