Golang中指针与接口的赋值问题:A = nil、A = B 且 B != nil 的情况分析

Golang中指针与接口的赋值问题:A = nil、A = B 且 B != nil 的情况分析

你使用的Go版本是什么(go version)?

Go Playground上的版本

这个问题在最新版本中是否重现?

如果Go Playground是最新版本,那么是的

你使用的操作系统和处理器架构是什么(go env)?

不适用

你做了什么?

https://play.golang.org/p/jM2mOSkKo-a

你期望看到什么?

期望打印以下内容之一:

interfaceSlice[1] == ps[1]
ps[1] == nil
interfaceSlice[1] == nil

或者仅打印:

ps[1] == nil

实际看到了什么?

实际打印:

ps[1] == nil
interfaceSlice[1] == ps[1]

我想了解导致这种情况的原因


更多关于Golang中指针与接口的赋值问题:A = nil、A = B 且 B != nil 的情况分析的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

感谢乔恩,我认为你的回答中唯一缺少的细节是:当左操作数没有显式类型时(如 12nil),等号运算符会假定其类型与右操作数相同。

更多关于Golang中指针与接口的赋值问题:A = nil、A = B 且 B != nil 的情况分析的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


这是一个关于Go语言中接口和指针赋值行为的经典问题。让我通过代码示例来解释这个现象:

package main

import "fmt"

type Person struct {
    Name string
}

func main() {
    var interfaceSlice []interface{}
    var ps []*Person
    
    // 情况1: 直接赋值nil
    ps = append(ps, nil)
    interfaceSlice = append(interfaceSlice, ps[0])
    
    // 情况2: 通过指针变量赋值
    var p *Person = nil
    ps = append(ps, p)
    interfaceSlice = append(interfaceSlice, ps[1])
    
    fmt.Printf("ps[0] == nil: %t\n", ps[0] == nil)
    fmt.Printf("interfaceSlice[0] == nil: %t\n", interfaceSlice[0] == nil)
    fmt.Printf("interfaceSlice[0] == ps[0]: %t\n", interfaceSlice[0] == ps[0])
    
    fmt.Printf("ps[1] == nil: %t\n", ps[1] == nil)
    fmt.Printf("interfaceSlice[1] == nil: %t\n", interfaceSlice[1] == nil)
    fmt.Printf("interfaceSlice[1] == ps[1]: %t\n", interfaceSlice[1] == ps[1])
}

原因分析:

  1. 接口的nil判断机制

    • 一个接口值由两部分组成:类型(type)和值(value)
    • 只有当类型和值都为nil时,接口才等于nil
    • 当你将一个具体类型的nil指针赋给接口时,接口的类型信息被设置为*Person,值被设置为nil
  2. 代码执行逻辑

    // ps[1]是*Person类型的nil指针
    ps[1] == nil  // true,因为这是具体类型的nil比较
    
    // interfaceSlice[1]是interface{}类型,包含(*Person, nil)
    interfaceSlice[1] == nil  // false,因为类型不是nil
    interfaceSlice[1] == ps[1]  // true,因为两者都包含相同的类型和值
    
  3. 更清晰的示例

var p *Person = nil
var i interface{} = p

fmt.Printf("p == nil: %t\n", p == nil)        // true
fmt.Printf("i == nil: %t\n", i == nil)        // false
fmt.Printf("i == p: %t\n", i == p)            // true

这就是为什么你会看到ps[1] == nil为true,而interfaceSlice[1] == nil为false,但两者比较却相等的原因。接口保持了原始指针的类型信息,即使其值为nil。

回到顶部