Go语言nil:空值/零值
在 Go 语言中,布尔类型的零值(初始值)为 false,数值类型的零值为 0,字符串类型的零值为空字符串"",而指针、切片、映射、通道、函数和接口的零值则是 nil。
nil 是Go语言中一个预定义好的标识符,有过其他编程语言开发经验的开发者也许会把 nil 看作其他语言中的 null(NULL),其实这并不是完全正确的,因为Go语言中的 nil 和其他语言中的 null 有很多不同点。
下面通过几个方面来介绍一下Go语言中 nil。
nil 标识符是不能比较的
package main import (
"fmt"
) func main() {
fmt.Println(nil==nil)
}
运行结果如下所示:
PS D:\code> go run .\main.go
# command-line-arguments
.\main.go:8:21: invalid operation: nil == nil (operator == not defined on nil)
//这点和 python 等动态语言是不同的,在 python 中,两个 None 值永远相等。
>>> None == None
True
从上面的运行结果不难看出,==对于 nil 来说是一种未定义的操作。
nil 不是关键字或保留字
nil 并不是Go语言的关键字或者保留字,也就是说我们可以定义一个名称为 nil 的变量,比如下面这样:
var nil = errors.New("my god")
虽然上面的声明语句可以通过编译,但是并不提倡这么做。
nil 没有默认类型
package main import (
"fmt"
) func main() {
fmt.Printf("%T", nil)
print(nil)
}
运行结果如下所示:
PS D:\code> go run .\main.go
# command-line-arguments
.\main.go:9:10: use of untyped nil
不同类型 nil 的指针是一样的
package main import (
"fmt"
) func main() {
var arr []int
var num *int
fmt.Printf("%p\n", arr)
fmt.Printf("%p", num)
}
运行结果如下所示:
PS D:\code> go run .\main.go
0x0
0x0
通过运行结果可以看出 arr 和 num 的指针都是 0x0。
不同类型的 nil 是不能比较的
package main import (
"fmt"
) func main() {
var m map[int]string
var ptr *int
fmt.Printf(m == ptr)
}
运行结果如下所示:
PS D:\code> go run .\main.go
# command-line-arguments
.\main.go:10:20: invalid operation: arr == ptr (mismatched types []int and *int)
两个相同类型的 nil 值也可能无法比较
在Go语言中 map、slice 和 function 类型的 nil 值不能比较,比较两个无法比较类型的值是非法的,下面的语句无法编译。
package main import (
"fmt"
) func main() {
var s1 []int
var s2 []int
fmt.Printf(s1 == s2)
}
运行结果如下所示:
PS D:\code> go run .\main.go
# command-line-arguments
.\main.go:10:19: invalid operation: s1 == s2 (slice can only be compared to nil)
通过上面的错误提示可以看出,能够将上述不可比较类型的空值直接与 nil 标识符进行比较,如下所示:
package main import (
"fmt"
) func main() {
var s1 []int
fmt.Println(s1 == nil)
}
nil 是 map、slice、pointer、channel、func、interface 的零值
package main import (
"fmt"
) func main() {
var m map[int]string
var ptr *int
var c chan int
var sl []int
var f func()
var i interface{}
fmt.Printf("%#v\n", m)
fmt.Printf("%#v\n", ptr)
fmt.Printf("%#v\n", c)
fmt.Printf("%#v\n", sl)
fmt.Printf("%#v\n", f)
fmt.Printf("%#v\n", i)
}
运行结果如下所示:
PS D:\code> go run .\main.go
map[int]string(nil)
(*int)(nil)
(chan int)(nil)
[]int(nil)
(func())(nil)
<nil>
零值是Go语言中变量在声明之后但是未初始化被赋予的该类型的一个默认值。
不同类型的 nil 值占用的内存大小可能是不一样的
一个类型的所有的值的内存布局都是一样的,nil 也不例外,nil 的大小与同类型中的非 nil 类型的大小是一样的。但是不同类型的 nil 值的大小可能不同。
package main import (
"fmt"
"unsafe"
) func main() {
var p *struct{}
fmt.Println( unsafe.Sizeof( p ) ) // 8 var s []int
fmt.Println( unsafe.Sizeof( s ) ) // 24 var m map[int]bool
fmt.Println( unsafe.Sizeof( m ) ) // 8 var c chan string
fmt.Println( unsafe.Sizeof( c ) ) // 8 var f func()
fmt.Println( unsafe.Sizeof( f ) ) // 8 var i interface{}
fmt.Println( unsafe.Sizeof( i ) ) // 16
}
运行结果如下所示:
PS D:\code> go run .\main.go
8
24
8
8
8
16
Go语言nil:空值/零值的更多相关文章
- 【Go入门教程2】内置基础类型(Boolean、数值、字符串、错误类型),分组,iota枚举,array(数值),slice(切片),map(字典),make/new操作,零值
这小节我们将要介绍如何定义变量.常量.Go内置类型以及Go程序设计中的一些技巧. 定义变量 Go语言里面定义变量有多种方式. 使用var关键字是Go最基本的定义变量方式,与C语言不同的是Go把变量类型 ...
- 【Go入门教程4】变量(var),常量(const),内置基础类型(Boolean、数值 byte,int,rune、字符串、错误类型),分组,iota枚举,array(数值),slice(切片),map(字典),make/new操作,零值
这小节我们将要介绍如何定义变量.常量.Go 内置类型以及 Go 程序设计中的一些技巧. 定义变量 Go 语言里面定义变量有多种方式. 使用 var 关键字是 Go 最基本的定义变量方式,与 C 语言不 ...
- Swift语言指南(六)--可选值
原文:Swift语言指南(六)--可选值 在值可能不存在的情况下使用可选值(optional), 可选值是: · 存在一个值,这个值等于 x 或 · 不存在任何值 注: 在 C 和 Objective ...
- c语言main函数返回值、参数详解(返回值是必须的,0表示正常退出)
C语言Main函数返回值 main函数的返回值,用于说明程序的退出状态.如果返回0,则代表程序正常退出:返回其它数字的含义则由系统决定.通常,返回非零代表程序异常退出. 很多人甚至市面上的一些书籍,都 ...
- 浮点数比较问题(float x 与 '零值'比较)
今天在牛客网上看到一道面试题,看完之后着实吃了一惊,自己平常都没有在意,看似简单的问题,实则考验了语言的基本功. 据说这是腾讯的面试题: float x 与“零值”比较的if语句为? if (x == ...
- Js 中的false,零值,null,undefined和空字符串对象
转自 http://www.imkevinyang.com/2009/07/javascript-中的false零值nullundefined和空字符串对象.html 在Javascript中,我们 ...
- R语言中的特殊值 NA NULL NaN Inf
这几个都是R语言中的特殊值,都是R的保留字, NA:Not available 表示缺失值 用 is.na() 来判断是否为缺失值 NULL:表示空值,即没有内容 用 is.null() 来判 ...
- golang之类型零值初始化及比较
综述 变量声明时未赋初值,则变量被自动赋值为该类型的零值(固定值) func new(Type) *Type new()返回一个指针,指向新分配的该类型的零值,不是空指针(nil).the value ...
- C语言:整数取值范转及溢出
short.int.long 是C语言中常用的三种整数类型,分别称为短整型.整型.长整型.在现代操作系统中,short.int.long 的长度分别是 2.4.4 或者 8,它们只能存储有限的数值,当 ...
随机推荐
- ios 10 更新 新体验
1.使用手机登录开发者网站https://developer.apple.com/download/ 2.下载描述文件 3.安装描述文件,按照提示步骤操作 4.更新ios系统 下面的方法是连接电脑直接 ...
- AtCoder-3867
Find the maximum possible sum of the digits (in base 10) of a positive integer not greater than N. C ...
- 洛谷 题解 P1287 【盒子与球】
题解:P1287 盒子与球 不了解的:stirling数(斯特林数) - 百度百科 分析如下: 设有n个不同的球,分别用b1,b2,--bn表示.从中取出一个球bn,bn的放法有以下两种: 1) bn ...
- 一些demo
绑定端口demo: #include <stdio.h> #include <sys/socket.h> #include <stdlib.h> #include ...
- Bootstrap响应式栅格系统设计
为了方便起见,我们通过1200px宽的屏幕来讲解bootstrap中container.row.col的css属性值为何这样设置的原理 在1200px屏幕中为何container的宽度设置为1170p ...
- 【Vuejs】301- Vue 3.0前的 TypeScript 最佳入门实践
前言 我个人对更严格类型限制没有积极的看法,毕竟各类转类型的骚写法写习惯了. 然鹅最近的一个项目中,是 TypeScript+ Vue,毛计喇,学之...-真香! 1. 使用官方脚手架构建 npm i ...
- 基于RT-Thread的人体健康监测系统
随着生活质量的提高和生活节奏的加快,人们愈加需要关注自己的健康状况,本项目意在设计一种基于云平台+APP+设备端的身体参数测试系统,利用脉搏传感器.红外传感器.微弱信号检测电路等实现人体参数的采集,数 ...
- 获取浏览器视口高度device-width
在进行移动设备web开发时,我们总会用到这样一条代码“<meta name='viewport' content='width=device-width,initial-scale=1.0' / ...
- Java 从入门到进阶之路(十四)
在之前的文章我们介绍了一下 Java 中的抽象类和抽象方法,本章我们来看一下 Java 中的接口. 在日常生活中,我们会接触到很多类似接口的问题,比如 USB 接口,我们在电脑上插鼠标,键盘,U盘的时 ...
- SSM项目整合纪实
一 前 言 本来是为了探究一些功能性问题,需要一套完整的项目架构,本以为SSM用过那么多了,轻松搭建不在话下,但是过程中还是遇到一些问题,踩到一些未曾料想的坑.博文以搭建极简架构为目的,附带一些关键阐 ...