本文主要来分析一下在golang中,如何判断interface是否为nil,以及相关注意事项。

正常情况下,我们声明一个interface类型的变量,默认值将会返回nil,以golang自带的io.Writer为例

var writer io.Writer
fmt.Printf("writer is nil => %t\n", writer == nil)

当然我们也可以用具体的实现结构来定义一个指针变量,它的默认值也是nil

var bufWriter *bufio.Writer
fmt.Printf("bufWriter is nil => %t\n", bufWriter == nil)

输出结果与上述的一样

以上的输出都是我们预期中的结果。

在实际开发中我们经常会碰到从某个函数中返回interface实例的情况,例如

bufWriter := func() io.Writer {
var w *bufio.Writer
fmt.Printf("w is nil => %t\n", w == nil)
return w
}()
fmt.Printf("bufWriter is nil => %t\n", bufWriter == nil)

此时我们的返回值是否仍旧与预期中的一致呢?

结果好像跟我们预想的有一些不太一样,因为在匿名函数中返回的是一个定义但是还未赋值的指针类型,并且在函数内部判断时,已经输出该变量为nil了,但是当我们在外部接收到这个值的时候,似乎变成非nil状态了

看着好像有一些诡异

那么,让我们来实际调用一下这个接口的函数试试

bufWriter := func() io.Writer {
var w *bufio.Writer
fmt.Printf("w is nil => %t\n", w == nil)
return w
}()
if bufWriter != nil {
bufWriter.Write([]byte("golang"))
}

可以看到,我们明明已经进行非空判断了,结果还是panic了

这是怎么回事呢?

其实当我们使用==直接将一个interface与nil进行比较的时候,golang会对interface的类型和值分别进行判断。

如果两者都为nil,在与nil直接比较时才会返回true,否则直接返回false。所以上面代码中interface与nil进行比较时返回的是false,因为此时interface变量的值是nil,但是他的类型不是nil,已经有了明确的实现类型,即bufio.Writer。因而当我们调用这个interface的函数成员时,就会直接panic。

所以在实际开发中,当interface类型的返回值已经明确为nil时,应该直接返回nil,而不是具体实现结构的未赋值空指针

bufWriter := func() io.Writer {
var w *bufio.Writer
if w == nil {
return nil
}
return w
}()
if bufWriter != nil {
bufWriter.Write([]byte("golang"))
} else {
fmt.Println("bufWriter is nil")
}

可以看到,此时我们可以正确判断interface是否为nil了

那么有没有办法去判断interface的真实值是否为nil呢?

当然可以,答案就是使用反射,示例如下:

bufWriter := func() io.Writer {
var w *bufio.Writer
fmt.Printf("w is nil => %t\n", w == nil)
return w
}()
fmt.Printf("bufWriter is nil => %t\n", bufWriter == nil)
fmt.Printf("IsNil => bufWriter is nil => %t\n", reflect.ValueOf(bufWriter).IsNil())

可以看到,当我们通过反射来判断是否为nil时,获取到了与我们预期一样的结果

参考资料

Why is my nil error value not equal to nil?

在golang中如何正确判断接口是否为nil的更多相关文章

  1. Golang中如何正确的使用sarama包操作Kafka?

    Golang中如何正确的使用sarama包操作Kafka? 一.背景 在一些业务系统中,模块之间通过引入Kafka解藕,拿IM举例(图来源): 用户A给B发送消息,msg_gateway收到消息后,投 ...

  2. 在Golang中如何正确地使用database/sql包访问数据库

    本文记录了我在实际工作中关于数据库操作上一些小经验,也是新手入门golang时我认为一定会碰到问题,没有什么高大上的东西,所以希望能抛砖引玉,也算是对这个问题的一次总结. 其实我也是一个新手,机缘巧合 ...

  3. Java中使用JSONTokener判断接口返回字符串是JSONObject还是JSONArray

    今天在接口对接中,遇到一个问题,对方接口返回的JSONString,类型不确定,所以需要先做判断再进行处理.查阅资料后使用JSONTokener可进行处理,特此记录. String ret = ord ...

  4. golang中的类和接口的使用

    类使用:实现一个people中有一个sayhi的方法调用功能,代码如下: type People struct { //.. } func (p *People) SayHi() { fmt.Prin ...

  5. 六、golang中的结构体和方法、接口

    结构体: 1.用来自定义复杂数据结构 2.struct里面可以包含多个字段(属性) 3.struct类型可以定义方法,注意和函数的区分 4.strucr类型是值类型 5.struct类型可以嵌套 6. ...

  6. golang中的接口实现(一)

    golang中的接口实现 // 定义一个接口 type People interface { getAge() int // 定义抽象方法1 getName() string // 定义抽象方法2 } ...

  7. golang中接口interface和struct结构类的分析

    再golang中,我们要充分理解interface和struct这两种数据类型.为此,我们需要优先理解type的作用. type是golang语言中定义数据类型的唯一关键字.对于type中的匿名成员和 ...

  8. 七、golang中接口、反射

    一.接口定义 1.定义 interface类型可以定义一组方法,但是这些不需要实现,并且interface不能包含任何变量 package main import ( "fmt" ...

  9. Golang 中的 面向对象: 方法, 类, 方法继承, 接口, 多态的简单描述与实现

    前言: Golang 相似与C语言, 基础语法与C基本一致,除了广受争议的 左花括号 必须与代码同行的问题, 别的基本差不多; 学会了C, 基本上万变不离其宗, 现在的高级语言身上都能看到C的影子; ...

  10. golang中判断两个slice是否相等

    在golang中我们可以轻松地通过==来判断两个数组(array)是否相等,但遗憾的是slice并没有相关的运算符,当需要判断两个slice是否相等时我们只能另寻捷径了. slice相等的定义 我们选 ...

随机推荐

  1. 如何在 Linux 上扫描/检测新的 LUN 和 SCSI 磁盘

    当 Linux 系统连接到 SAN(存储区域网络)后,你需要重新扫描 iSCSI 服务以发现新的 LUN. 要做到这一点,你必须向存储团队提供 Linux 主机的 WWN 号和所需的 LUN 大小. ...

  2. Linux服务器中了挖矿木马怎么办?-挖矿木马自助清理手册

    什么是挖矿木马 挖矿木马会占用CPU进行超频运算,从而占用主机大量的CPU资源,严重影响服务器上的其他应用的正常运行.黑客为了得到更多的算力资源,一般都会对全网进行无差别扫描,同时利用SSH爆破和漏洞 ...

  3. MFC调用外部dll时,出现无法解析的外部符号的解决方法)

    最近在一个MFC工程文件中调用了多个dll和lib文件,包括matlab和can连接文件,时常出现"无法解析的外部符号"的错误,特此记录解决方法.   通常出现这个问题的原因有以下 ...

  4. Spring RMI 介绍

    Spring RMI RMI全称是Remote Method Invocation-远程方法调用,是纯Java的网络分布式应用系统的核心解决方案之一.Java RMI 支持存储于不同地址空间的程序级对 ...

  5. 在Unity3D中开发的Ghost Shader

    SwordMaster Ghost Shader 特点 此Shader是顶点片元Shader,由本人手动编写完成 此Shader已经在移动设备真机上进行过测试,可以直接应用到您的项目中 所支持的Uni ...

  6. c++ read and save txt

    read and save #include "util/image_util.h" #ifdef USE_PANGOLIN_VIEWER #include "pango ...

  7. docker出现“Failing to start dockerd: failed to create NAT chain DOCKER”错误

    使用Windows的WSL 2里面的Ubuntu安装docker之后,启动docker服务一直失败,提示Docker is not running.使用dockerd命令会出现如下错误: INFO[2 ...

  8. Mysql explain 每个属性含义

    Mysql explain explain 常用于分析sql语句的执行效率,使用时在正常的select语句之前添加explain并执行就会返回执行信息,返回的执行信息如下:  id:id列的编号是se ...

  9. Linux系列---【U盘插入后,linux系统如何查看U盘中的内容?】

    U盘插入后,linux系统如何查看U盘中的内容? 1.插入U盘 2.输入命令查看U盘是否插入成功 sudo fdisk -l 输入上面命令后,在最下面Device Boot一栏查看自己的U盘所在的分区 ...

  10. 05 HDFS Java API应用实例

    一.在Ubuntu系统中安装和配置Eclipse 二.利用hadoop 的java api,向HDFS写一个文件. 三.从HDFS读取一个文件的内容.