zoukankan      html  css  js  c++  java
  • 在golang中如何正确判断接口是否为nil

    本文主要来分析一下在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?

    Write By 陌上荼靡
  • 相关阅读:
    Asp.net中文本框全选的实现
    如何在Sql Server中读取最近一段时间的记录,比如取最近3天的或最近3个月的记录。
    asp.net存储过程分页+GridView控件 几百万数据 超快
    Gridview各种功能+AspNetPager+Ajax实现无刷新存储过程分页 (留着用)
    asp.net导出EXCEL的好方法!(好用,导出全部数据)
    GridView分页的实现 ASP.NET c#(转)特好用
    asp.net c# repeater或gridview导出EXCEL的详细代码。
    c#实现word,excel转pdf代码及部分Office 2007文件格式转换为xps和pdf代码整理
    C# WORD操作实现代码(转载)
    如何提高程序员的生产率 (2)
  • 原文地址:https://www.cnblogs.com/mstmdev/p/15696177.html
Copyright © 2011-2022 走看看