[13th][Day15] nil

nil 空值

什麽? nil 是一种资料型态? 还是 nil 值? 你在跟我开玩笑吗?

不只是 golang ... 在每个语言中 nil 都是非常重要的,它代表的是空。
而 ... 在不同语言中,「空」的概念都有些细微的不同。

比方说 ...
在 scheme 中,nil 是 true 的!
在 C 中 NULL 跟 0 是等价的。

昨天说到 golang 的任何变数型态在宣告时,都对应到一个初值

false for booleans
0 for numeric
"" for strings
nil for pointers, functions, interfaces, slices, channels, and maps

golang 中的 nil 是不同於其他语言的,为了理解 nil,我们来一点一点、慢慢地揭开 nil 神秘的面纱

nil 是不能被比较的,没有这种东西:

if nil == nil

nil 可以出现在 if 的右边,常用於错误判断

if err != nil {
    log.println(err)
    return
}

不同资料型态的 nil 的 address 是一样的

	var m map[int]string
	var ptr *int
	fmt.Printf("%p", m)
	fmt.Println("")
	fmt.Printf("%p", ptr)

输出为

0x0
0x0
m 是一个 map,ptr 是一个 pointer
但 ... m 和 ptr 的 address 都是 0x0

nil 是 map,slice,pointer,channel,func,interface 的初值

	var m map[int]string
	var ptr *int
	var c chan int
	var sl []int
	var f func()
	var i interface{}
	fmt.Printf("%#v\n", m)
	fmt.Printf("%#v\n", ptr)
	fmt.Printf("%#v\n", c)
	fmt.Printf("%#v\n", sl)
	fmt.Printf("%#v\n", f)
	fmt.Printf("%#v\n", i)

输出为
map[int]string(nil)
(*int)(nil)
(chan int)(nil)
[]int(nil)
(func())(nil)

注意:struct 的初值不是 nil,而是该 struct 旗下,每个变数自己的初值。且不能将 struct 类型和 nil 进行比较,会跳红字,无法编译

nil 不是 golang 的关键字
而且 ... nil 的值可以被更改(下面是个不好的示范

	nil := 123
	fmt.Println(nil) // 123

	// The following line fails to compile,
	// for nil represents an int value now
	// in this scope.
	var _ map[string]int = nil

纯属娱乐,请勿这样使用,如果造成其他不可预期的後遗症 ...
请不要来找我(X

PS: null 以及 NULL 在许多其他语言也不是关键字


不同资料型态的 nil 值的大小可能会有所不同
同型态变数所占的记忆体都是相同的,nil 值占记忆体的大小始终与类型与 nil 值相同的非 nil 值的大小相同。
but ...,不同变数型态的 nil 的记忆体可能具有不同的大小。

	var p *struct{} = nil
	fmt.Println( unsafe.Sizeof( p ) ) // 8

	var s []int = nil
	fmt.Println( unsafe.Sizeof( s ) ) // 24

	var m map[int]bool = nil
	fmt.Println( unsafe.Sizeof( m ) ) // 8

	var c chan string = nil
	fmt.Println( unsafe.Sizeof( c ) ) // 8

	var f func() = nil
	fmt.Println( unsafe.Sizeof( f ) ) // 8

	var i interface{} = nil
	fmt.Println( unsafe.Sizeof( i ) ) // 16

对 golang 来说,相同变数型态的两个值的大小 nil 始终相同。
ex:所有不同的 slice 来说,当 slice 为空时,其 nil 值的大小都相同。

nil 是 golang 中一个熟悉而重要的 default 值。它是很多资料型态 零值(zero values)的表示方式。 很多有一些其他语言转 go 的开发人员视 nil 为他语言 null (或者 NULL) 的复制品

恩 ... 有部分是正确的,但是 Go 中的 nil 和其他语言的 null(或者 NULL)有很多不同之处。
ex : 我们可以直接使用 nil 而不用宣告他。

理解 nil 是学习 golang 一个很重要的部分。

nil 之所以比较难以理解,是因为我们经常搞混 nil value 和 nil type 的区别,value vs type 当然是不一样的哦 >.^

从上面 nil slice和 empty slice 的不同 延伸,其实 empty slice 也可以作为 slice 的 zero value。特地发明一个 nil 值,应该是 golang 出於对性能的考虑。

nil pointer 其实是一切 nil 值的根本型态,可以使用的部分就这麽多
能省下的记忆体就先省下来,pointer 就先让他 nil 着。

if err != nil {
panic(err)
}

Go 有自己特殊的错误处理方式(例如 Java 使用 try..catch),正因为错误发生时,是传回错误,所以有许多方式可以检查错误

nils in Go


<<:  ESP32_DAY11 短路

>>:  Day 13:vim 设定档

为了转生而点技能-javascript,day3(观念厘清-执行绪与同步、非同步

执行绪与同步、非同步 本篇是统整网路上各资源节录而成,如有观念错误的地方,还请大大们多多鞭策。 名词...

Windows Server 2012 R2 安装微软免费防毒软件 Microsoft Security Essentials

在 Windows Server 的作业系统上都是预设无防毒软件的,可是没有防毒软件就会让电脑曝露在...

让API 返回 Kafka- producer.send 事件 use Promise

这边使用的是nodejs(egg) 一张图简介一下 ELK+kafka做什麽用 (用於数据分析,lo...

JS读书笔记30天 - Day30 感想

缘由 因为拖延症严重,想要强迫自己看课,所以如果把每天进度都写成了铁人30天的文章,为了不中断,造成...

【Day 14】OSM 浅谈 part 2

OSM 我们来看看 开放地图 的介面。 看起来就像是个复杂版的 google map,对吧 OSM ...