ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

在golang中如何正确判断接口是否为nil

2021-12-16 03:31:07  阅读:168  来源: 互联网

标签:nil fmt Writer 接口 bufWriter golang Printf interface


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

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

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

image

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

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

输出结果与上述的一样

image

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

在实际开发中我们经常会碰到从某个函数中返回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)

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

image

结果好像跟我们预想的有一些不太一样,因为在匿名函数中返回的是一个定义但是还未赋值的指针类型,并且在函数内部判断时,已经输出该变量为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了

image

这是怎么回事呢?

其实当我们使用==直接将一个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了

image

那么有没有办法去判断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时,获取到了与我们预期一样的结果

image

参考资料

Why is my nil error value not equal to nil?

标签:nil,fmt,Writer,接口,bufWriter,golang,Printf,interface
来源: https://www.cnblogs.com/mstmdev/p/15696177.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有