• Go语言 nil:空值/零值


    nil 标识符是不能比较的

    package main
    
    import "fmt"
    
    func main() {
        fmt.Println(nil == nil)
    }
    .
    il.go:6:18: invalid operation: nil == nil (operator == not defined on nil)

    nil 不是关键字或保留字

    nil 并不是Go语言的关键字或者保留字,也就是说我们可以定义一个名称为 nil 的变量,比如下面这样:

    var nil = errors.New("my god")

    虽然上面的声明语句可以通过编译,但是并不提倡这么做。

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

    package main
    
    import "fmt"
    
    func main() {
    
        //fmt.Println(nil == nil)
    
        var arr []int
        var num *int
        var string *string
        fmt.Printf("%p
    ", arr)
        fmt.Printf("%p
    ", num)
        fmt.Printf("%p
    ", string)
    
    }
    0x0
    0x0
    0x0

    通过运行结果可以看出 arr 、num、 string 的指针都是 0x0。

    不同类型的 nil 是不能比较的

    package main
    
    import "fmt"
    
    func main() {
    
        var arr []int
        var num *int
        var string *string
        fmt.Printf("%p
    ", arr)
        fmt.Printf("%p
    ", num)
        fmt.Println(arr == num)
    
    }
    .
    il.go:14:18: invalid operation: arr == num (mismatched types []int and *int)

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

    在Go语言中 map、slice 和 function 类型的 nil 值不能比较,比较两个无法比较类型的值是非法的,下面的语句无法编译。

    var s1 []int
        var s2 []int
        fmt.Printf("
    ", s1 == s2)
    .
    il.go:16:22: invalid operation: s1 == s2 (slice can only be compared to nil)

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

    package main
    
    import "fmt"
    
    func main() {
    
      
    
        var m map[int]string
        var ptr *int32
        var c chan int32
        var slice []int32
        var f func()
        var i interface{}
    
        fmt.Printf("%#v 
    ", m)
        fmt.Printf("%#v 
    ", ptr)
        fmt.Printf("%#v 
    ", c)
        fmt.Printf("%#v 
    ", slice)
        fmt.Printf("%#v 
    ", f)
        fmt.Printf("%#v 
    ", i)
    }
    map[int]string(nil)
    (*int32)(nil)
    (chan int32)(nil)
    []int32(nil)
    (func())(nil)
    <nil>

    零值是Go语言中变量在声明之后但是未初始化被赋予的该类型的一个默认值。

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

    一个类型的所有的值的内存布局都是一样的,nil 也不例外,nil 的大小与同类型中的非 nil 类型的大小是一样的。但是不同类型的 nil 值的大小可能不同。

    package main
    
    import (
        "fmt"
        "unsafe"
    )
    
    func main() {
    
        // var arr []int
        // var num *int
        // var string *string
        // fmt.Printf("%p
    ", arr)
        // fmt.Printf("%p
    ", num)
        // fmt.Println(arr == num)
    
        // var s1 []int
        // var s2 []int
        // fmt.Printf("
    ", s1 == s2)
    
        var m map[int]string
        var ptr *int32
        var c chan int32
        var slice []int32
        var f func()
        var i interface{}
    
        fmt.Printf("%#v 
    ", m)
        fmt.Printf("%#v 
    ", ptr)
        fmt.Printf("%#v 
    ", c)
        fmt.Printf("%#v 
    ", slice)
        fmt.Printf("%#v 
    ", f)
        fmt.Printf("%#v 
    ", i)
    
        fmt.Println(unsafe.Sizeof(m))
        fmt.Println(unsafe.Sizeof(ptr))
        fmt.Println(unsafe.Sizeof(c))
        fmt.Println(unsafe.Sizeof(slice))
        fmt.Println(unsafe.Sizeof(f))
        fmt.Println(unsafe.Sizeof(i))
    }
    map[int]string(nil)
    (*int32)(nil)
    (chan int32)(nil)
    []int32(nil)
    (func())(nil)
    <nil>
    8
    8
    8
    24
    8
    16

    具体的大小取决于编译器和架构,上面打印的结果是在 64 位架构和标准编译器下完成的,对应 32 位的架构的,打印的大小将减半。

  • 相关阅读:
    Android Studio 快捷键、Debug的使用
    android 控件获取 获取焦点
    jquery里面获取div区块的宽度与高度
    C# ASP.NET MVC 配置允许跨域访问
    分页跳转计算公式
    在vue-cli3 中import引入一个没有export default{}的js文件
    vue中引入css文件
    Vue 导入文件import、路径@和.的区别
    npm 如何查看一个包的版本信息?
    Chrome浏览器常用键盘快捷键介绍
  • 原文地址:https://www.cnblogs.com/personblog/p/12260345.html
Copyright © 2020-2023  润新知