nil的本质

官方文档:

nil 是一个预先声明的标识符,表示指针、通道、函数、接口、map或slice 类型的零值。

// 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

// Type is here for the purposes of documentation only. It is a stand-in

// for any Go type, but represents the same type for any given function

// invocation.

type Type int

由此可见nil的值就是默认初始化的0,nil实质是一个代表了0的变量

nil的作用

仅仅告诉编译器如何去初始化这一类型的数据,不一定不占用内存,不用把它单纯地当做java,c++里面的null

怎么来论证呢?slice大家知道吧,slice的原型就是一个struct,你说struct的0值是啥意思呢?所以可以大胆给出结论:nil是给编译器用来初始化(pointer, channel, func, interface, map, or slice type)的零值情况的,具体要不要占用内存各自要看实际情况

下面我看看slice的原型: (为了便于强转我们命名为slice2)

type slice2 struct {

pointer unsafe.Pointer

len int

cap int

}

func main() {

var s  []int=nil

fmt.Printf("%p\n", s)         //0x0

fmt.Printf("%p\n", &s)        //0xc000004078 举例

fmt.Println("size:",unsafe.Sizeof(s)) //这里是会占用内存的

p:=unsafe.Pointer(&s)

ps:=(*slice2)(p)

ps.len=12

fmt.Println(len(s)) //被改变了....,说明s其结果如上,且是占用内存的

fmt.Printf("%p\n",ps.pointer)

}

结果如下:

0x0

0xc000004078

size: 24

12

0x0

Ps:empty slice和nil slice的区别在于,数组指针是否赋值了,所有的empty数组指针固定执行一个空数组地址

容易我们可以用上面的方法论证其他情况,但注意map是hmap的指针语法糖,下面举例看看interface

type eface struct { // empty inteface的大概原型

_type unsafe.Pointer

data  unsafe.Pointer

}

func testInterface() {

var pint interface{} =nil

p := unsafe.Pointer(&pint)

ps := (*eface)(p)

temp:=33

ps._type = unsafe.Pointer(&temp)

fmt.Println(pint == nil)  //false

}

func main() {

testInterface()

}

结论:

nil是给编译器用来初始化(pointer, channel, func, interface, map, or slice type)的零值情况的,具体要不要占用内存各自要看实际情况

初始化零值的情况,不能简单地说不会占用内存,也不要把它当做空指针来看待.

发表回复