我有一个接口,它定义了一个类型为func(interface{}, proto.Message) interface{}
的参数,并且我试图将func reduceMsg(a interface{}, b proto.Message) []*PersistentData
类型的内容传递给它。这会导致以下编译器错误:
Cannot use reduceMsg (type func(a interface{}, b proto.Message) []*PersistentData as type func(interface{}, proto.Message) interface{}
出现此错误的原因是什么,我该如何解决?似乎返回比interface{}
更合适的类型应该是合法的。这是一个简单的完整示例,说明了这个问题:
package main
import "fmt"
func main() {
var t func() interface{} = func() []string { return []string{} }
fmt.Println(t)
}
答案 0 :(得分:2)
对象的类型是整个函数签名。如果签名不匹配,则它不是同一类型,不能以这种方式分配。
任何东西都可以分配给空接口,因为所有类型都满足接口,但在你的问题中,类型都不是空接口,你只需要一个返回空接口的函数。
不是因为函数的一部分可以分配给另一个函数而是因为它是相同的。类型是整个函数签名。我认为无法将int
分配给int8
背后的逻辑是相同的。您可以根据需要进行投射,但是对于go,它们是单独的类型,您需要处理必要的转换才能分配它们。
您可以做的是更改第二个函数签名以返回如下所示的空接口:
func(interface{}, proto.Message) interface{}
func reduceMsg(a interface{}, b proto.Message) interface{} {
var a []*PersistentData
// do something here
return a
}
这样功能签名是相同的,因此它考虑相同的类型,并且您返回[]*PersistentData
。当然,在使用它之前你需要做一个类型断言,因为程序会将它视为{}interface
,因为这是函数返回的类型。
答案 1 :(得分:1)
在赋值中,每个值必须可赋值给它所分配的操作数的类型,具有以下特殊情况:
- 可以将任何类型的值分配给空白标识符。
- 如果为接口类型的变量或空标识符分配了无类型常量,则首先将常量转换为其默认类型。
- 如果为接口类型的变量或空标识符分配了无类型的布尔值,则首先将其转换为bool类型。
转让性
在任何这些情况下,值x都可分配给T类型的变量(" x可分配给T"):
- x的类型与T相同。
- x的类型V和T具有相同的基础类型,并且V或T中的至少一个不是命名类型。
- T是接口类型,x实现T。
- x是双向通道值,T是通道类型,x类型V和T具有相同的元素类型,并且V或T中的至少一个不是命名类型。
- x是预先声明的标识符nil,T是指针,函数,切片,地图,通道或接口类型。
- x是一个无类型常量,可由类型T的值表示。
通常,Go不允许您隐式地将值从一种类型转换为另一种类型,除了能够使用具体类型的对象,就好像它们是接口(它们实现的)。
在这种特殊情况下,由于你的函数实际上没有返回interface{}
,编译器必须做一些额外的工作来将返回值包装为interface{}
并返回它;如果你真的想要完成你正在尝试的事情,你可以自己明确地做到这一点:
type Foo struct {
X int
}
func create(x int) Foo {
return Foo{X: x}
}
func main() {
var f func(int) interface{} = func(x int) interface{} {
return create(x)
}
}
基本上(显式地)执行您希望运行时隐式执行的包装操作。