我命由我,不由天!


  • 搜索
prometheus docker golang linux kubernetes

go中的nil

发表于 2021-07-10 | 分类于 golang | 0 | 阅读次数 217

nil 是什么

在源码builtin.go定义中,nil是一个Type类型的变量

var nil Type
type Type int

nil适用于指针,函数,interface,map,slice,channel这6种类型

变量定义:

分配变量指定大小的内存,确定一个变量名称。Go 确保分配出来的内存块里面是全 0 数据

所以,记住这句话,nil 是编译器识别行为的一个触发点而已,看到这个 nil 会触发编译器的一些特殊判断和操作。

slice

定义

  • 第一种 var 的方式定义变量纯粹真的是变量定义,如果逃逸分析之后,确认可以分配在栈上,那就在栈上分配这 24 个字节,如果逃逸到堆上去,那么调用 newobject 函数进行类型分配。
  • 第二种 make 方式则略有不同,如果逃逸分析之后,确认分配在栈上,那么也是直接在栈上分配 24 字节,如果逃逸到堆上则会导致调用 makeslice 函数来分配变量。

nil 判断

  1. 指针值为 0 的,也就是说这个动态数组没有实际数据的时候。

  2. 只对首字段 array 做非 0 判断,len,cap 字段不做判断。

map

定义

// 变量定义
var m1 map[string]int
// 定义 & 初始化
var m2 = make(map[string]int)

  • 第一种方式仅仅定义了 m1 变量本身;
  • 第二种方式则是分配 m2 的内存,还会调用 makehmap 函数(不一定是这个函数,要看逃逸分析的结果,如果是可以栈上分配的,会有一些优化)来创建某个结构,并且把这个函数的返回值赋给 m2;

nil 判断

搞懂了变量本身和管理结构的区别就很简单了,这里的 nil 值判断也仅仅是针对变量本身的判断,只要是非 0 指针,那么就是非 nil 。也就是说 m1 只要是一个非 0 的指针,就不会是非nil 的。

interface

变量本身

type iface struct {
    tab  *itab
    data unsafe.Pointer
}

type eface struct {
    _type *_type
    data  unsafe.Pointer
}

其中,iface 就是通常定义的 interface 类型,eface 则是通常人们常说的空接口 对应的数据结构。

不管内部怎么样,这两个结构体占用内存是一样的,都是一个正常的指针类型和一个无类型的指针类型( Pointer ),总共占用 16 个字节。

也就是说,如果你声明定义一个 interface 类型,无论是空接口,还是具体的接口类型,都只是分配了一个 16 字节的内存块给你,注意是置 0 分配哦。

nil 赋值

和上面类似,如果对一个 interface 变量赋值 nil 的话,发生的事情也仅仅是把变量本身这 16 个字节的内存块置 0 而已。

nil 值判断

判断 interface 是否是 nil ?这个跟 slice 类似,也仅仅是判断首字段(指针类型)是否为 0 即可。因为如果是初始化过的,首字段一定是非 0 的。

  • 本文作者: Dante
  • 本文链接: https://gaodongfei.com/archives/g-o-zhong-de-n-i-l
  • 版权声明: 本博客所有文章除特别声明外,均采用CC BY-NC-SA 3.0 许可协议。转载请注明出处!
# golang
kafka
使用nfs作为pv
  • 文章目录
  • 站点概览
Dante

Dante

119 日志
5 分类
5 标签
RSS
Creative Commons
0%
© 2023 Dante
由 Halo 强力驱动
|
主题 - NexT.Pisces v5.1.4
沪ICP备2020033702号