8.28Go之容器之nil

nil的特点

  • 是Go语言中一个预定义好的标识符

  • 是"指针、切片、映射、通道、函数、接口的零值"

nil与null不同点

nil标识符是不能比较的

==对于 nil 来说是一种未定义的操作

package main

import "fmt"

func main() {
fmt.Println(nil == nil)
}
/*
会提示
# command-line-arguments
.\NilPractice.go:6:18: invalid operation: nil == nil (operator == not defined on nil)
*/

nil不是关键字或保留字

可以定义一个名为nil的变量

package main

import "fmt"

func main() {
   nil := "Hello"
   fmt.println(nil)
   /*这在Go语言中是合法的*/
}

nil没有默认类型

package main

import "fmt"

func main() {
fmt.Printf("%T", nil)
print(nil)
}

不同类型nil的指针是一样的

package main

import "fmt"

func main() {
/*声明两个变量*/
var arr []int
var num *int

/*分别利用格式化输出他们的nil值*/
fmt.Printf("%p\n", arr)
fmt.Printf("%p", num)
/*
fmt.Printf方法返回一个整数类型的值
和常规的空值验证
*/
}
//arr 和 num 的指针都是 0x0

指针指向的内存地址不一样:

package main

import "fmt"

func main() {
/*声明两个变量*/
var arr []int
var num *int

/*分别利用格式化输出他们的nil值*/
fmt.Printf("%p\n", &arr)
fmt.Printf("%p", &num)
/*
fmt.Printf方法返回一个整数类型的值
和常规的空值验证
*/
}
//这两个的结果是不一样的

不同类型的nil值不能比较

package main

import "fmt"

func main() {
/*声明两个变量*/
var mapValue map [int] string
var ptr *int

fmt.Printf(mapValue == ptr)
}
/*
这会导致编译无法通过
*/

两个相同类型的nil值也可能无法比较

map、slice 和 function 类型的 nil 值不能比较。会导致编译不通过

package main

import "fmt"

func main() {
   /*声明两个切片*/
   var num1 []int
   var num2 []int
   
   fmt.Printf(num1 == num2)
   fmt.Printf(num1 == nil) //这也会导致编译无法通过--->不能将空值直接与nil标识符进行比较
}

nil 是 map、slice、func、pointer、channel、interface 的零值

package main
import (
   "fmt"
)
func main() {
   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)
}

不同类型的nil值占用的内存大小可能是不一样的

  • 一个类型的所有的值的内存布局都是一样的,nil 的大小与同类型中的非 nil 类型的大小是一样的。

  • 不同类型的 nil 值的大小可能不同。

package main
import (
   "fmt"
   "unsafe"
)
func main() {
   var p *struct{}
   fmt.Println( unsafe.Sizeof( p ) ) // 8
   var s []int
   fmt.Println( unsafe.Sizeof( s ) ) // 24
   var m map[int]bool
   fmt.Println( unsafe.Sizeof( m ) ) // 8
   var c chan string
   fmt.Println( unsafe.Sizeof( c ) ) // 8
   var f func()
   fmt.Println( unsafe.Sizeof( f ) ) // 8
   var i interface{}
   fmt.Println( unsafe.Sizeof( i ) ) // 16
}

总结

  • nil不是Go语言当中预先定义好的标识符或保留字,可以作为变量名

  • 不同类型的nil无法比较,相同类型的nil有可能也无法比较

  • nil是引用类型的零值,map、slice、function的nil值无法比较--->其他的引用类型是可以的

It's a lonely road!!!