GoLang nil与interface的空指针深入分析
作者:alwaysrun 发布时间:2024-02-18 01:58:50
nil
Go中,每个指针都有2个基本信息,指针的类型和指针的值(type,value);当执行==
时,需要比较类型与值(只有类型与值都相等时,才会相等)。
nil并不是Go语言的关键字或者保留字,而是一个预定义好的标识符:
nil之间不能比较:
nil==nil
是不允许的,会抛出operator == not defined on untyped nil
异常;不同类型的nil之间不能互相比较:如切片的nil,不能与map的nil做比较;
nil是
map、slice、pointer、channel、func、interface
的零值;不同类型nil值占用空间可能大小不同;
在64位机器上运行时nil的大小:
func main() {
var p *struct{}
fmt.Println(unsafe.Sizeof(p), p == nil) // 8
var s []int
fmt.Println(unsafe.Sizeof(s), s == nil) // 24
var m map[int]bool
fmt.Println(unsafe.Sizeof(m), m == nil) // 8
var c chan string
fmt.Println(unsafe.Sizeof(c), c == nil) // 8
var f func()
fmt.Println(unsafe.Sizeof(f), f == nil) // 8
var i interface{}
fmt.Println(unsafe.Sizeof(i), i == nil) // 16
}
slice
一个nil的slice,除了不能索引外,其他的操作都正常;当append元素时,slice会自动进行扩容。
slice是一个简单的结构体,包含(长度、容量、指向数组的指针);当slice为nil时,长度、容量都为0,指针为空。
map
一个nil的map,是一个真正的空指针,除len与for-range外,其他操作不能正常使用。
非nil的map,是一个指向内部HashMap的指针;空map(map[string]int{}
)与为nil的map是不同的,空map只是没有内容,可在上面做任何的map操作。
interface
interface底层由两部分组成(参见《golang反射简介》),一个是类型,一个值,也就是类似于:(Type, Value)。只有当类型和值都是nil的时候,才等于nil:
func inFun(v interface{}) {
fmt.Println("fun-interface:", v == nil)
}
func main() {
var a interface{}
var b []string
var c string
fmt.Println(a == nil)
inFun(a) // true
fmt.Println(b == nil)
inFun(b) // false
//fmt.Println(c == nil) // can not compare with nil
inFun(c) // false
}
// true
// fun-interface: true
// true
// fun-interface: false
// fun-interface: false
本身是interface时,传递interface参数,其nil属性不变;若是普通指针,则传递给interface参数时,都为非空(!=nil);
指针是否为空
那如何判定interface里面的动态值是否空?此时需要借助反射reflect来实现:
func nilCheck(v interface{}) {
defer func() {
if err := recover(); err != nil {
fmt.Println("panic:", err)
}
}()
if v == nil {
fmt.Println("nilCheck: interface is nil")
return
}
vi := reflect.ValueOf(v)
fmt.Println("nilCheck:", vi.IsNil())
}
func main() {
var a interface{}
var b []string
var c string
nilCheck(a)
nilCheck(b)
nilCheck(c)
}
// nilCheck: interface is nil
// nilCheck: true
// panic: reflect: call of reflect.Value.IsNil on string Value
对于非指针类型,在反射后调用IsNil时会抛出异常。其实现:
func (v Value) IsNil() bool {
k := v.kind()
switch k {
case Chan, Func, Map, Pointer, UnsafePointer:
if v.flag&flagMethod != 0 {
return false
}
ptr := v.ptr
if v.flag&flagIndir != 0 {
ptr = *(*unsafe.Pointer)(ptr)
}
return ptr == nil
case Interface, Slice:
// Both interface and slice are nil if first word is 0.
// Both are always bigger than a word; assume flagIndir.
return *(*unsafe.Pointer)(v.ptr) == nil
}
panic(&ValueError{"reflect.Value.IsNil", v.kind()})
}
来源:https://blog.csdn.net/alwaysrun/article/details/127598335
猜你喜欢
- 至此,我们的 Python零基础入门篇 的系列专栏到今天基本上算是结束了。今天没有任何的知识点,只是运用我们之前学习过的知识做两个小游戏的案
- 我就废话不多说了,直接上代码吧!#!/usr/bin/env python# coding:UTF-8"""@
- Python文件遍历os.walk()与os.listdir()在图片处理过程中,样本数据的组织是个常见的问题,样本组织好了,后面数据转换、
- 一、Scrapy框架简介Scrapy是用纯Python实现一个为了爬取网站数据,提取结构性数据而编写的应用框架,用途非常广泛。利用框架,用户
- 主要功能在copyFiles()函数里实现,如下:def copyFiles(src, dst): sr
- 现在拥有了正则表达式这把神兵利器,我们就可以进行对爬取到的全部网页源代码进行筛选了。下面我们一起尝试一下爬取内涵段子网站:http://ww
- 通常操作系统和软件开发包中都包含文本编辑器,可以用来编辑配置文件,文档文件和源代码。下面是笔者总结的10个最好的免费代码文本编辑器:1.NO
- 前言:相信大家在童年或者生活中都玩过石头剪刀布这个游戏,这个游戏需要两个及以上的人。而今天,网上也实现了石头剪刀布的游戏。通过初步学习pyt
- 这篇文章我们学习 Python 变量与数据类型变量变量来源于数学,是计算机语言中能储存计算结果或能表示值抽象概念,变量可以通过变量名访问。在
- 查看当前用户拥有的系统权限 select * from user_sys_privs; 系统权限 系统管理员授予-----sys用户 cre
- django-mdeditorGithub地址:https://github.com/pylixm/django-mdeditor 欢迎试用
- 目的我们的目标是安装一个允许我们托管多个网站的web服务器,其中一些是针对电子商务的安全解决方案,而大部分网站是通过连接一个数据库服务器并且
- 鉴于上一篇中最后三个问题:1、上述程序是否能进行优化(比如功能相同的)2、创建三个3个实例,用了3个语句,能否建一个函数,只输入一个数n,就
- 如下所示:import jsonimport http.clientconnection = http.client.HTTPSConnec
- 我们的每期话题,团队在内部都会通过邮件进行一番讨论,随着讨论的激烈,往往能碰撞出很多有意义的观点,因此,将讨论内容分享出来,有兴趣的朋友可以
- 总的来讲,JavaSever PagesTM(JSP)和 微软的Active Sever Pages(ASP)在技术方面有许多相似之处。两者
- 1. 将数据库生成使用对象资源管理器能快速创建整个数据的脚本,也能使用默认选项创建单个数据库对象的脚本;用户能在查询编辑器窗口中对文件或剪贴
- 一、os模块os.getcwd() 获取当前的工作目录os.chdir(‘绝对路径/相对于当前工作目录的路径&r
- mysql安装好经常发现无法正常启动碰到最多的是error 2003的错误,以下为解决方法: mysqld -nt -remove mysq
- 今天在intellij调试spark的时候感觉每次有新的一段代码,都要重新跑一遍,如果用spark-shell,感觉也不是特别方便,如果能像