当前位置: 首页 > 面试题库 >

作为接口传递时,nil slice不是nil!为什么?(golang)

穆招
2023-03-14
问题内容

看到这个游乐场:http :
//play.golang.org/p/nWHmlw1W01

package main

import "fmt"

func main() {
    var i []int = nil
    yes(i) // output: true
    no(i)  // output: false
}

func yes(thing []int) {
    fmt.Println(thing == nil)
}

func no(thing interface{}) {
    fmt.Println(thing == nil)
}

为什么两个函数的输出不同?


问题答案:

诚然,这有点古怪,但是有一个解释。

想象一个interface{}变量是由两个字段组成的结构:一个是类型,另一个是数据。([]intnil)。实际上,它看起来就像Go运行时中的样子。

struct Iface                                                                                                                   
{                                                                                                                              
    Itab*   tab;                                                                                                               
    void*   data;                                                                                                              
};

当您将nil slice传递给时yes,只会nil将其作为值传递,因此您的比较可简化为nil == nil

同时,调用会no自动将您的变量包装为一种interface{}类型,并且调用变得类似于no(interface{[]int, nil})。因此,in中的比较no可以看成interface{[]int, nil} == nil,这在进行中被证明是错误的。

该问题实际上在Go
FAQ
中得到了解释。



 类似资料:
  • 问题内容: 我有一个带有接口参数的函数: 我如何通过它传递一个零值,使其通过检查? 方法1: 方法二: 由于https://golang.org/doc/faq#nil_error,第二种方法不起作用 游乐场:https : //play.golang.org/p/V0bMSPcCKI 问题答案: 使用以下内容创建: 问题中的第一种方法不起作用,因为表达式返回。nil接口值的具体类型为nil。 诀

  • 问题内容: 为什么我的内部类中没有接口?为什么是天生的?抱歉,如果这是一个愚蠢的问题,我已经尽力一遍又一遍地用Google搜索,但似乎无法将其包裹在脑海中。如为什么不能在内部类/局部类中声明这些? 同样作为一个确认,我们在接口中可以包含静态最终变量的原因是因为它们未指定状态或任何此类实现权?如果我们输了而只使用了final,那么我们需要一个没有意义的实例,因为您无法实例化接口。抱歉,我真的很困惑,

  • 现在,调用可能会调用的copy构造函数(它很可能是copy省略的,所以情况并非如此)。但将导致复制。如果包含大量数据,则可能是一个问题。 我们将通过将其作为常量引用()传递来改进它,以消除不需要的副本。只要是就可以。如果不是,则调用将导致编译错误(丢失限定符)。 所以,为什么要费心使用常量引用,只使用reference()。这很好,但对于第一种情况就不起作用了,因为将r-value绑定到(非常量)

  • 问题内容: 我有以下定义: 我尝试按如下方式调用它,但收到错误消息: 这符合: 问题答案: 该相关转到FAQ中指出,和«别在内存相同的表示»。 要了解原因,让我们剖析两件事: 切片是一个后备存储阵列,外加几个包含切片大小和容量的整数。 在Go中,数组并不是某种意义上的“高级”。相反,它们包含的元素的布局是严格定义的:它们全部包含在内存的相邻区域中,彼此相邻。 这意味着,在切片的支持数组中,元素是类

  • 问题内容: 我有一个界面: 和一个实现它的类 第三类实现了此方法: 现在我试图像这样调用该方法 但我不断得到一个例外说: 如果它连接了该类,该方法不起作用吗? 问题答案: 也许你需要

  • 学习Java8默认方法。这个链接就像互联网上的其他资源一样说 在“最严格的意义上”,默认方法是一种倒退,因为它们允许你用代码“污染”你的接口。但它们提供了允许向后兼容的最优雅和最实用的方法。它使Oracle更容易更新所有集合类,也使您更容易为Lambda修改现有代码。 我的理解是Java8Dev/Designers在接口中提供了默认方法,这样所有实现类就不必不必要地重写相同的行为,从而提供了向后兼