在golang中如何正确判断接口是否为nil
本文主要来分析一下在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的更多相关文章
- Golang中如何正确的使用sarama包操作Kafka?
Golang中如何正确的使用sarama包操作Kafka? 一.背景 在一些业务系统中,模块之间通过引入Kafka解藕,拿IM举例(图来源): 用户A给B发送消息,msg_gateway收到消息后,投 ...
- 在Golang中如何正确地使用database/sql包访问数据库
本文记录了我在实际工作中关于数据库操作上一些小经验,也是新手入门golang时我认为一定会碰到问题,没有什么高大上的东西,所以希望能抛砖引玉,也算是对这个问题的一次总结. 其实我也是一个新手,机缘巧合 ...
- Java中使用JSONTokener判断接口返回字符串是JSONObject还是JSONArray
今天在接口对接中,遇到一个问题,对方接口返回的JSONString,类型不确定,所以需要先做判断再进行处理.查阅资料后使用JSONTokener可进行处理,特此记录. String ret = ord ...
- golang中的类和接口的使用
类使用:实现一个people中有一个sayhi的方法调用功能,代码如下: type People struct { //.. } func (p *People) SayHi() { fmt.Prin ...
- 六、golang中的结构体和方法、接口
结构体: 1.用来自定义复杂数据结构 2.struct里面可以包含多个字段(属性) 3.struct类型可以定义方法,注意和函数的区分 4.strucr类型是值类型 5.struct类型可以嵌套 6. ...
- golang中的接口实现(一)
golang中的接口实现 // 定义一个接口 type People interface { getAge() int // 定义抽象方法1 getName() string // 定义抽象方法2 } ...
- golang中接口interface和struct结构类的分析
再golang中,我们要充分理解interface和struct这两种数据类型.为此,我们需要优先理解type的作用. type是golang语言中定义数据类型的唯一关键字.对于type中的匿名成员和 ...
- 七、golang中接口、反射
一.接口定义 1.定义 interface类型可以定义一组方法,但是这些不需要实现,并且interface不能包含任何变量 package main import ( "fmt" ...
- Golang 中的 面向对象: 方法, 类, 方法继承, 接口, 多态的简单描述与实现
前言: Golang 相似与C语言, 基础语法与C基本一致,除了广受争议的 左花括号 必须与代码同行的问题, 别的基本差不多; 学会了C, 基本上万变不离其宗, 现在的高级语言身上都能看到C的影子; ...
- golang中判断两个slice是否相等
在golang中我们可以轻松地通过==来判断两个数组(array)是否相等,但遗憾的是slice并没有相关的运算符,当需要判断两个slice是否相等时我们只能另寻捷径了. slice相等的定义 我们选 ...
随机推荐
- windows U盘启动装机工具(Ventoy)
Windows优盘启动装机工具 一.WePE 纯净 WePE 启动盘/ U盘重装系统工具 1.U盘重装系统工具下载地址:https://www.wepe.com.cn/download.html?td ...
- nginx 配置react项目 并且开启gzip压缩
#user nobody; worker_processes 1; #error_log logs/error.log; #error_log logs/error.log notice; #erro ...
- 阿里开源的几个中间件 dubbo/RocketMQ/canal/druid 代码还是很不错的
阿里开源的几个中间件 dubbo/RocketMQ/canal/druid 代码还是很不错的
- 随机生成不重复的几个数(Unity)
using System.Collections.Generic; using UnityEngine; /// <summary> /// 随机数管理类 /// </summary ...
- Postgresql统计所有表的基本信息(如行数、大小等)
目录 pg_class 记录表和几乎所有具有列或者像表的东西.这包括索引(但还要参见 pg_index ).序列.视图.物化视图.组合类型和TOAST表,参见 relkind .下面,当我们提及所有这 ...
- vivado程序示例
//full_add.v 全加器 module full_add( input a, input b, input carry, output sum, output count ); assign ...
- 后台调用 WEBAPI 几种方式
示例是调用谷歌短网址的API. 1. HttpClient方式: public static async void DoAsyncPost() { DateTime dateBegin = DateT ...
- 2html5
多媒体标签 <audio> <audio src='../audio/bxb.mp3' controls="controls" autoplay="au ...
- Ext.form.ComboBox 中如何移除事件,如何添加事件,动态设置事件
Ext.form.ComboBox 中如何移除事件,如何添加事件 背景: 希望Ext.form.ComboBox动态设置forceSelection属性,动态控制Combobox的可读可写状态,是否允 ...
- Java发送http请求携带token,使用org.nutz
发送http请求,需要携带token数据,创建Header传输 Header header = Header.create(); header.set("Authorization" ...