理解Golang中的nil

参考:

有趣的面试题:Go语言中的nil比较 - 知乎 (zhihu.com)

理解Go语言的nil - 简书 (jianshu.com)

Golang中的nil,没有人比我更懂nil! - 知乎 (zhihu.com)

常用的nil

在写程序的时候经常会遇到nil这个词,比如说错误判断:

f, err := os.Open(filePath)
if err != nil {
    panic(err)
}

这很容易理解,但是有如果对nilnil进行比较,如下:

fmt.Println(nil== nil)

我第一反应是true,但是能作为面试题,肯定不会那么简单。显然是我太菜了,那么今天就来扒一扒nil

nil的官方定义

查看Golang的官方定义builtin - The Go Programming Language (golang.org)

nil is a predeclared identifier representing the zero value for a pointer, channel, func, interface, map, or slice type.

var nil Type // Type must be a pointer, channel, func, interface, map, or slice type

翻译之后,总结起来,nil是:

  • 一个标识符(并不是关键字)
  • 预先定义零值
  • 针对
    • pointer
    • channel
    • func
    • interface
    • map
    • slice
nil是一个标识符

nil不是一个关键字,只是一个标识符。这就说明你可以自己定义一个变量去覆盖它。

这是可以编译通过的,但是不建议那么做。

nil有类型吗

从定义可知,nil是多个类型的零值,这些类型之间的差别很大,那么nil怎么能表示这些零值,而且nil有类型吗?

我尝试将nil赋值给变量a并打印出来,会显示use of untyped nil;

也就是说,nil是没有默认类型的,使用nil的时候必需提供充足的上下文信息来让编译器推断其类型。

使用nil比较
nil与nil进行比较

回归上面的面试题,对nil和nil进行比较,结果如下:

编译没有通过,显示的错误为操作==在nil中没有定义==符号对于nil来说是一种未定义的操作,所以不可以来比较两个nil

不同类型的nil比较

不同类型之间的nil进行比较,结果如何呢?

可以看到,不同类型之间的nil是无法进行比较的,显示为mismatched types

各种类型的零值与地址

那么,不同类型的零值实际上是什么?我们尝试来打印各种类型nil的实际GO语法表示地址

总结起来如下:

类型值的Go语法表示address
mapmap[int]string(nil)0x0
pointer (*int)(*int)(nil)0x0
channel(chan int)(nil)0x0
slice[]int(nil)0x0
func(func())nil0x0
interface<nil>%!p(<nil>)

可以看到大部分地址都是相同的,每种类型nil的实际表示并不是一致的,所以不同类型nil不能进行比较。

总结

总的来说,nil值一个针对map等类型预先定义的零值的标识符。由于不是关键字,所以写代码中要注意不要使用nil作为变量名。nil的类型是不定的,会根据具体的定义环境而发生改变,这就要求我们在对nil进行比较时要特别注意。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值