美文网首页
GO基础学习(5)nil

GO基础学习(5)nil

作者: 温岭夹糕 | 来源:发表于2023-04-24 23:30 被阅读0次

写在开头

非原创,知识搬运工,本节介绍了nil的底层结构,nil的类型
demo代码地址

往期回顾

  1. 基本数据类型
  2. slice/map/array
  3. 结构体
  4. 接口

带着问题去阅读

  1. nil可以被篡改吗
  2. 两个nil可能不相等吗
  3. nil可以有哪些类型
  4. 该demo有错误吗?如果有请指明原因
a := nil
  1. nil的长度是多少

1.什么是nil

首先抛出问题,我们默认nil是零值,为什么不能和0比较

nil == 0 

go文档中将nil的解释为,是一个预定义的标识符zero value,它不是关键词,同时他也不是基础类型和函数类型,是被单独罗列的。
上面文档的解释太少,我们再从源码中寻找蛛丝马迹,在go的文件buildin/buildin.go中定义了很多内置类型,其中

// 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 Type int //这里的int不是整数类型是交给汇编的

从注释中我们可以得到以下信息:
1.它是一个预定义标识符针
2.它代表的是一个零值
3.这些零值的类型即Type必须是一个指针/通道/函数/接口/map/slice类型

1.1实验验证

所以为啥开头的不能和0比较明白了吧?0是int类型,与结构体比较也是错误的,它不在上面罗列的范围内demo

var s student
t.Log(s==nil)

nil和其他复杂类型作比较demo,这里其实之前在接口那一章详细提到过,不同的数据结构比较规则不同,如接口是T和V全为空值时才为nil,和底层数据结构挂钩

    type A interface{}
    type B struct{}
    var a *B //a是一个指针
    var m map[int]int
    var ch chan int
    var f func()
    var s []int

    t.Log(a == nil)
    t.Log(m == nil)
    t.Log(ch == nil)
    t.Log(f == nil)
    t.Log(s == nil)

结果全为true,这里还需要注意map、slice和ch在声明后,没用make赋值是不能使用的,不是代表空的通道或者map,是真的一个零值地址,强行操作则抛出异常

panic: assignment to entry in nil map [recovered]

 panic: assignment to entry in nil map

这是因为这些复杂类型跟nil的比较不单是值的比较
再对nil进行类型转化demo

func TestNiltoAnotherType(t *testing.T) {
    type B struct{ name string }
    var a *B //a是一个指针

    t.Log(a == nil)            //零值指针 true
    t.Log(a == (*B)(nil))      //true

}

需要注意的是当我们直接写出来nil时,它是没有类型的,或者说编译器没法确定它的类型,这是不合法的nil类型demo

func TestStateNil(t *testing.T) {
    a := nil
    t.Log(a) // use of untyped nil in assignment
}

nil是Go中唯一没有默认类型的非类型值。必须有足够的信息让编译器从上下文中推断出nil的类型。
合法的nil类型就是上面这种

var a *B

那么不同的nil就有不同的长度demo

func TestSizeofNil(t *testing.T) {
    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
}

还需要注意的是,既然它是用var声明的就意味着和js的undefined的一样是可以被用户自己覆盖的

func TestChangeNil(t *testing.T) {
    var nil int = 1
    a := 1
    t.Log(a == nil) //此时就能通过
}

最后不同类型的nil类型比较时也需要注意,这篇博客贴了一个因不同类型nil产生的坑

参考

1.go101-nil
2.没有人比我更懂Nil

相关文章

  • Go nil != nil

  • go 基础学习

    1 go 基础go 语法基础go 官方资料如果由C ,C++ 基础, 学习go 比较容易,本文学习go ,主要是为...

  • Go Nil

    Go语言数据类型中,布尔类型的零值(初始值)为false,数值类型的零值为0,字符串类型的零值为空字符串""。 对...

  • Go接口之nil != nil

    本文来自“灰子学技术”,原文链接如下所示:https://mp.weixin.qq.com/s/ZBd1UcIJF...

  • go语言学习

    基础 go的学习,感谢Go By Example、go网络编程与go语言标准库随着学习的深入,此文章持续更新......

  • go语言学习-从基础到实战到源码分析

    收集的一些go语言学习资料,有go基础学习系列,go项目实战,go进阶-go源码分析,还有go的一些书籍,go的架...

  • go http学习笔记

    go http学习笔记 @[goweb, go, http] 1.go http基础 go http服务器简例 h...

  • 从0开始Go语言,用Golang搭建网站

    实践是最好的学习方式 零基础通过开发Web服务学习Go语言 本文适合有一定编程基础,但是没有Go语言基础的同学。 ...

  • 初识Go语言-1

    Go语言学习路径 初识Go语言 Go语言环境搭建与IDE安装 Go语言基础语法 Go语言数据类型 Go语言变量和常...

  • 【Golang】golang中使用defer关闭file句柄总是

    实例: 查看源码发现,go标准包中,如果打开文件出错,将返回nil的文件类型,而nil类型的变量调用Close()...

网友评论

      本文标题:GO基础学习(5)nil

      本文链接:https://www.haomeiwen.com/subject/welpjdtx.html