什么是nil?go中关于nil的定义为(buildin.go中):

var nil Type
type Type int

go定义变量时,会默认分配一个零值,如:bool->false、numbers -> 0 、string -> “” 。而nil则为指针、切片、map、通道、函数对象、接口对象的零值,nil可以代表多种对象,如下代码:

var a = nil       //此代码报错,因为编译器无法确定a的数据类型
var a = (int*)(nil)   //代码正确

指针nil:表示指向一个地址为0的地址,如下我们手动构造一个指针nil:

var a = (*int)(unsafe.Pointer(uintptr(0x0)))
fmt.Println(a == nil)  //true

切片nil:
切片的底层结构为:

type slice struct {array unsafe.Pointerlen   intcap   int
}///runtime包的slice.go中

切片由三部分构成,当指针为nil,切片就为nil。

type MySlice struct {pointer unsafe.Pointerlen intcap int
}

由于我们不能直接控制切片底层数据,创建MySlice对象映射slice结构,控制切片地址数据。

func main() {var sli1 = []int{}var sli2 []intvar sli3 = make([]int, 4)fmt.Println(1,sli1 == nil) //false,因为做了初始化,pointer不为nilfmt.Println(2,sli2 == nil) //true,未做初始化,pointer为nil//此时,s1指向了切片底层的slice对象(src/runtime/slice.go中定义)s1 := (*MySlice)(unsafe.Pointer(&sli1))s1.pointer = nilfmt.Println(3,sli1 == nil) //true, 即使len和cap不为0,pointer为nils2 := (*MySlice)(unsafe.Pointer(&sli2))s3 := (*MySlice)(unsafe.Pointer(&sli3))s2.pointer = s3.pointer//s2和s3共用底层数组s2.cap = 2s2.len = 2fmt.Println(4,sli2 == nil) //false,pointer不为nil,指向sli3的底层数组sli3[0] = 500fmt.Println(5,sli2[0], sli3[0]) //500 500  共用底层数组sli2[1] = 700fmt.Println(6,sli2[1], sli3[1]) //700 700  共用底层数组
}

以上示例通过底层模拟构造,访问切片底层数据,实际编码勿用。

chanel & map & func的nil:这三位大哥非常复杂,简单来说就是指向一个固定结构的指针。

interface的nil:接口也是一种数据类型,每种数据类型都有类型(Type)和值(Value),通过reflect.TypeOf()和reflect.ValueOf()可以获取类型和值。接口是一种虚拟的数据类型,任何实现了接口的对象,都可以给接口赋值。因此,当获取接口的类型和值时,获取的是实际赋值的类型的值和对象。当比较接口时,只有当接口变量的数据类型和值都相等时,接口才相等。当给接口赋值为nil时,实际上相当于将接口的Type设置为nil,没有设置Value。示例代码如下:

func main() {type Interface interface{}type Struct struct{}var s *Struct = nilvar i Interfacefmt.Println(1, s == nil)                         //true,指针fmt.Println(2, s == (*Struct)(nil))              //true,相同类型指针比较fmt.Println(3, (Interface)(s) == (*Struct)(nil)) //true,接口的Type为实际数据类型的Type,他们的值都是nilfmt.Println(4, (Interface)(s) == nil)     //false,接口为nil时,表示Type类型为nil,value未设置,比较的前值Type为*Structfmt.Println(5, nil == i)              //true,接口为赋值,初始化Type为nil,Value未赋值fmt.Println(reflect.TypeOf(i), reflect.ValueOf(i))//<nil> <invalid reflect.Value>(表示未赋值)i = sfmt.Println(reflect.TypeOf(i), reflect.ValueOf(i))//*main.Struct <nil>
}

参考:https://zhuanlan.zhihu.com/p/151140497

go语言中,到底nil是个什么货?相关推荐

  1. Go语言中nil的理解

    现在对于Golang语言的介绍比较少,写一点自己对于nil的理解. 首先,我们取源代码中看一下创始人是怎么定义的nil 翻译如下: //nil是一个预先声明的标识符,表示指针.通道.函数.接口.映射或 ...

  2. c语言char str什意思,C语言中,charstr的str到底表示什么?

    问题:C语言中,char str的 str到底表示什么? 描述: #include int main() { #第一处 char *pstr = "abcdef"; printf( ...

  3. Lisp语言中的if语句

    目录 导言: 到底是if语句还是if函数? if语句的语法: 使用if语句: 关系函数: 逻辑函数: and函数: or函数: not函数: 导言: 在Lisp语言中拥有分支语句是一件十分正常的事情, ...

  4. 关于C语言中的malloc和free函数的用法

    一.malloc()和free()的基本概念以及基本用法: 1.函数原型及说明: void *malloc(long NumBytes):该函数分配了NumBytes个字节,并返回了指向这块内存的指针 ...

  5. malloc 初始化_在C语言中,请一定记得初始化局部变量!

    C语言中,未初始化的局部变量到底是多少? 答案往往是: 与编译器有关. 可能但不保证初始化为0. 未确定. 总之,全部都是些一本正经的形而上答案,这很令人讨厌. 但凡一些人给你滔滔不绝地扯编译器,C库 ...

  6. Java 语言中 Enum 类型的使用介绍

    Enum 类型的介绍 枚举类型(Enumerated Type) 很早就出现在编程语言中,它被用来将一组类似的值包含到一种类型当中.而这种枚举类型的名称则会被定义成独一无二的类型描述符,在这一点上和常 ...

  7. go语言中append函数的使用

    go语言中append处理slice 每次调用appen都会根据当前的cap对slice进行评估, 如果cap不够,就按照2倍长度进行扩容 package mainimport ("fmt& ...

  8. go语言中channel的创建和销毁以及匿名函数的使用

    channel的创建 go语言中,任意类型前面加上关键字chan即可声明对应类型的通道,创建通道需要使用make,make也用于map 和slice的创建 创建一个通道 /*刚创建的通道是nil*/ ...

  9. C语言中main函数的研究,以及对代码断点调试的研究(王爽老师 汇编语言)

    版权声明:本文为博主原创文章,未经博主允许不得转载. 我们知道作为一个语言本身是不会有诸如从main函数开始运行这样的条件(深层次的说 底层汇编代码不会指定从mian函数开始的这样的条件,程序开始的位 ...

最新文章

  1. Linux【命令】修改文件内容
  2. QT Creator使用matlab库文件读取.mat文件数据
  3. 二项分布均值和方差的简单推导
  4. Scala Case类和对象
  5. 信号与系统matlab课设报告,MATLAB信号与系统实验报告
  6. 一周学会HTML----Day03常用标签(下)
  7. Linux(Ubuntu 16) 下Java开发环境的配置(二)------Tomcat的配置及常见问题
  8. 【牛客 - 297D】little w and Exchange(上下界贪心)
  9. Nginx For Windows 路由配置
  10. Seesaw Loss:一种面向长尾目标检测的平衡损失函数
  11. topshelf和quartz内部分享
  12. Ansys 2022R2安装教程
  13. Linux下的经典软件-史上最全
  14. xp下的资源管理器界面上的前进后退等图标保持在系统哪里?shell32.dll里没有。
  15. 被巨头“封杀”后,中国移动互联网企业如何加速出海
  16. Android TextView 上下滑动 左右滑动设置
  17. 微信支付之App支付
  18. maven项目创建出错Could not calculate buil d plan:Plugin org.apache.maven.plugins 避坑
  19. c语言读取midi文件举例子,c# – 使用NAudio从MIDI文件中读取音符
  20. Spark 持久化(cache和persist的区别)

热门文章

  1. 欢迎来到物联网的世界
  2. 【FPGA-Spirit_V2】基于FPGA的循迹小车-小精灵V2开发板
  3. 复录比低的计算机学校,这7所报录比低的实力院校,赶紧捡漏一波!
  4. 微信html5切水果游戏,推荐这3个切水果的小游戏,打开微信小程序试试吧!
  5. 重装windows server 2003 R2 X64服务器
  6. “饭局门”背后的核心业务—投研与智能投研(下)
  7. asp.net报社图片库管理系统
  8. php启动失败80端口被占用,80端口被占用 Apache启动失败的解决方法
  9. C语言实现输入某年某月某日,判断这一天是这一年的第几天,并输出今年还剩下多少天?
  10. FileZilla等软件搭建ftp服务器