Go语言中的interface{}和C语言中的void*一样吗?

17

由于类型为interface{}的变量可以拥有任何值,这是否意味着它本质上像C语言中的void*那样是一个通用指针?


1
请阅读"Go数据结构:接口" - kostix
@kostix 感谢提供链接,但这篇文章有什么 golang 规范没有涵盖到的内容吗? - Brenden
它解释了实现细节,从中可以清楚地得出结论:interface{}不像C语言中的“通用指针void *”。 - kostix
@kostix,我更好奇Go如何将interface{}作为其他类型的通用容器的基本功能。 - Brenden
也许已经很晚了,但我真的很喜欢你的问题。 :) - Maciej Wawrzyńczuk
3个回答

22

虽然C语言的void *指针和Go语言的interface{}变量都具有存储任意类型数据的属性,但它们之间存在一个重要的区别:Go语言的接口变量还存储所持有值的类型。

因此,虽然C语言程序员需要确保从void *指针强制转换到特定类型时是安全的,但Go语言运行时可以检查任何类型断言是否正确。

接口变量中的类型信息还允许通过reflect包进行复杂的运行时内省,而使用普通的void *指针则无法实现这一点。


2
所以 interface{} 就像是带有 void* 和额外类型数据的 struct - Brenden
是的。类型信息还用于决定如何在非空接口类型上分派方法调用。 - James Henstridge

6

我倾向于说“完全不是!”但我承认它可能达到“持有任何东西”的目的。

  1. interface{}不是指针,因此无法对其进行解引用。
  2. 您可以将void*转换为任何类型,但类型断言interface{}可能会导致运行时崩溃。
  3. 确定void*指向的实际类型很复杂(或不可能),但包反射可让您对interface{}执行此操作。

所以不!interface{}是空接口,与C中的void*没有任何关系,只有一个小例外:两者都可以用于处理您不关心其真实性质的任何内容。


1
你可能想提到一个 interface{} 也可以包含原始类型,而 void * 指向某个东西(除非你非常不整洁,但不能保证所有 C 的原始类型都可以无损地转换为 void *)。 - Nick Craig-Wood
我认为这是一个关于正方形/矩形的问题。interface{}是一个void*,但是void*不是一个interface{}(因为接口除了指针还有其他功能)。这样说是否公平? - Brenden
@Brenden:不,我不认为有必要像这样解释空接口。所有这些“在语言Y中构造X就像在语言U中构造Z”的说法并不总是有帮助的。 - Volker
@Volker,将未知的概念与熟悉的概念联系起来是有帮助的。 - Brenden

0
不,如果涉及的接口类型为空——它没有任何方法——那么itable除了保存指向原始类型的指针之外就没有任何作用。在这种情况下,可以丢弃itable,让值直接指向该类型。REF: https://research.swtch.com/interfaces

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接