在Golang中将结构体指针转换为接口指针

44

我有一个函数

func doStuff(inout *interface{}) {
   ...
}

这个函数的目的是能够将任何类型的指针作为输入进行处理。但是当我想用一个结构体指针来调用它时,出现了错误。

type MyStruct struct {
    f1 int
}

在调用doStuff

ms := MyStruct{1}
doStuff(&ms)

我有

test.go:38: cannot use &ms (type *MyStruct) as type **interface {} in argument to doStuff

如何将&ms转换为与*interface{}兼容的类型?

1个回答

80

在技术上讲,“指向接口的指针”并不存在(尽管你可以使用它,但通常并不需要)。

正如在“what is the meaning of interface{} in golang?”中所述,interface是一个带有两个数据单词的容器:

  • 一个单词用于指向该值底层类型的方法表,
  • 另一个单词用于指向该值所持有的实际数据。

interface

因此,去掉指针,doStuff将完美地工作:接口数据将为您的指针&ms

func doStuff(inout interface{}) {
   ...
}

参见这个示例

ms := MyStruct{1}
doStuff(&ms)
fmt.Printf("Hello, playground: %v\n", ms)

输出:

Hello, playground: {1}

正如newacct评论中所提到的

直接将指针传递给接口能够工作,因为如果MyStruct符合协议,则*MyStruct也符合协议(因为类型的方法集包含在其指针类型的方法集中)。

在这种情况下,接口是空接口,因此它无论如何都接受所有类型,但仍然如此。


4
接口变量在内部的工作原理对于问题不相关。从语义上讲,接口变量包含了它所分配的值的副本,就像Go语言中的任何其他类型一样。在底层,它是通过一个不可变指向数据的指针实现的,但这对程序员来说是不可见的。 - newacct
7
直接将指针传递到接口中可行的原因是,如果 MyStruct 符合协议,则 *MyStruct 也符合该协议(因为类型的方法集包括在其指针类型的方法集中)。在这种情况下,接口是空接口,因此它仍然接受所有类型,但是最好还是加以说明。 - newacct
@newacct 很好的观点。我已经将您的第二条评论包含在答案中,以增加可见性。 - VonC
1
值得注意的是,您可以通过访问Type.Elem()函数来处理传递给函数的指针。这使您可以进行比较,例如reflect.TypeOf(&MyStruct{}).Elem() == reflect.TypeOf(MyStruct)。请参见https://play.golang.org/p/DGb87RUZqJ - notzippy

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