我最近读到了戈兰尼尔兔洞(Via),Andran进入了声明部分的方式:
所以这是一个有趣的事实,Go有多种“类型”的零。特殊地,有键入和没有型号的无变量。
你们中的一些人现在读到了你的键盘(CF),这也是我的第一次反应。努力谈论谈论某人有时会感到有时没有型号,因为Go'当你将它与其他一些功能结合起来时,有时候会有一些有趣的感觉。所以让'首先,在某些情况下,它的表现如何以及它的行为。
在代码中,文字' nil'有效地工作好像它是annunyped常数像' 0' (虽然它不是一个常数;它' s一个通过特殊语义的预先录制标识符。但是,只要使用nil,通过将其分配给传递它作为函数参数的可变常量时,刚刚使用nil,所以它是某种类型的指针,函数,切片,映射,频道或界面。对于可以是nil的具体类型(指针,函数,切片,映射和频道),甚至可以读取这些数值的类型。例如,FMT' S%TVERB将报告它,并且您可以检查此打字机反映。但是,这不是界面的情况。
就像其他大多数其他东西一样,键入界面,包括着名的空界面,接口{},以及结果如此interface值。 in的接口值仍然具有类型。无论何种方式,此接口类型(接口值)都是非常硬的toobserve(在代码中),因为go的另一个属性:将一个接口类型转换为另一个接口类型时,原始类型接口类型丢失。如果接口值不是nil,它具有底层的具体类型,保留了界面值,将界面值转换为另一个接口类型(尽管原始接口类型丢失)。但是,如果界面价值零,则没有底层混凝土类型,所以有保留的其他类型的信息;您可以' t告诉另一个接口类型的NIL OFONE类型。
现在我们到了微妙的去陷阱。 FMT都不是FMT,也不反映出来自Go类型系统的魔法豁免,以便接受近距离类型。相反,他们必须使用空界面的Go逃生舱口,接口{},一切都可以转换为此。但这意味着当您呼叫FMT或反映Anterface值时,您'重新执行接口转换,以及您丢失了原始接口值的类型。 Forinstance,假设您编写这样的代码:
错误类型是一个接口类型。调用fmt.printf时,错误接口值将转换为接口{}类型,并且fmt.printf现在无法访问E isan错误的事实;所有它可以报告的是混凝土底层类型,如果是一个。如果你打电话给#39; fred(nil)',fmt in turned type interface {}的passeda nil值{},只能耸耸听于最初值的whattype。
(通过扩展,fmt'%t'动词永远不会告诉你正在使用的interfaceType。如果您想知道,必须将Apointer传递给接口值,然后#39;%t'%t&# 39;那个,哪个' *错误'请参阅此游乐场示例,这表明这确实保留了NIL接口值的接口类型,就像您' D.)
从这个意义上讲,nil interface值是没有型号的,因为他们的rype很难动态地观察并在实践中审视非凡的go代码。由于这一点,很多完全正常的Go Codewill告诉你,这些价值没有类型(FMT' s'%t' verfiill报告他们的类型为'&#39 ;, 例如)。
(也许他们的类型应该报告为'界面{}'但是本身举行了,它不会成为更有用的志法士。)
这样做的另一种方法是需要界面{}参数的任何东西可以' t区分不同切接面类型的数量,并且通过扩展也可以' t区分与文字零和value internal inactal碰巧是nil(例如,因为它' sa值(接口)类型错误,没有错误)。 FMT和反映接口{}参数且由此受到限制。如果您'重新意识到这种无法区分,事情可以寻找令人费解的(或者您可以通过它被删除)。
(这是一个有时零的另一个方面有时不是nil,这足以拥有常见问题解答。)