Go 接口中 Nil 切片的特殊行为
在 Go 中,切片可以被赋予 nil 值,这表示一个空切片。然而,当将 nil 切片作为参数传递给需要接口{}的函数时,就会出现令人惊讶的行为差异。
考虑以下 Go 游乐场:
<code class="go">package main import "fmt" func main() { var i []int = nil yes(i) // output: true no(i) // output: false } func yes(thing []int) { fmt.Println(thing == nil) } func no(thing interface{}) { fmt.Println(thing == nil) }</code>
在上面的例子中,两个函数 yes 和 no 接收相同的 nil 切片作为它们的参数。但是,两个函数的输出不同。 yes 打印 true,表明切片确实为零。不,另一方面,打印 false。
为什么会出现这种差异?答案在于 Go 接口内部表示 nil 切片的方式。
interface{} 变量用于表示各种类型,由两个字段组成:类型和数据指针。当一个 nil 切片传递给需要一个 interface{} 的函数时,它会被包装在一个 interface{} 类型中,并且数据指针被设置为 nil。
在 yes 的情况下,它直接比较nil 的参数,有效地询问切片本身是否为零。此比较返回 true,因为切片确实为空。
但是,no 函数接收包装在 interface{} 中的 nil 切片。这种情况下的比较不仅仅是切片和 nil 之间的比较,而是整个 interface{} 和 nil 之间的比较。在运行时内部,这种比较归结为测试 interface{} 的数据指针是否为 nil,这是 false,因为接口包装器已为其分配了内存。
此行为也记录在 Go 的常见问题解答中:
“将 nil 切片传递给接口的一个常见问题:由于 nil 切片由 nil 接口值表示,因此在测试接口 i(nil 接口)的值时写入 if i == nil 可能会虚假成功是假的)。”
以上是为什么 Nil 切片在传递到 Go 中的接口时表现不同?的详细内容。更多信息请关注PHP中文网其他相关文章!