我正在做的事情:
我有一个库包,它定义了几种类型,都实现了给定的接口 . 在整个代码中,涉及回调,而不是在我为其定义类型的任何地方编写回调类型 .
type Foo interface {
Bar()
}
type MyCallback func(f Foo)
type CoolFoo int
type BadFoo int
func (cf *CoolFoo) Bar(cb MyCallback) {
}
func (bf *BadFoo) Bar(cb MyCallback) {
}
然后从使用该库的客户端代码开始,我想使用回调调用 . 如果我通过使用接口类型调用它,它可以工作:
cf := &CoolFoo{}
cf.Bar(func(f packageName.Foo) {
})
但我宁愿在我的IDE中有更多的自我记录代码和正确的类型提示,所以我尝试使用implementsor类型调用它,例如:
cf := &CoolFoo{}
cf.Bar(func(f packageName.CoolFoo) {
})
哪个编译失败,错误:
不能在cf.Bar的参数中使用func文字(类型为func(packageName.CoolFoo))作为类型packageName.MyCallback
这是不可能的,还是我犯了一些假的错误?我在开发方面不是很有经验,我试过环顾四周,但在这里找不到解决方案 .
我发现它是将它作为Foo或接口{}传递然后在回调中转换为我想要的,但我想避免它,因为它感觉凌乱
谢谢你的帮助
1 回答
函数签名是
func(f Foo)
,因此这正是必须传递的内容 . 原因很简单:如果您的方法需要该签名的回调函数,它可以传入任何实现Foo的类型 . 如果你传入一个只接受CoolFoo
的函数,调用者仍然可以传入BadFoo
,因为你传递给它的类型,它将会失败,因为你需要代码支持.1490561_t .如果你的回调只传递
CoolFoo
,那么这可能是你在签名中使用的类型 . 如果CoolFoo
和BadFoo
每个只将它们各自的类型传递给它们的回调,那么你可能需要两个不同的回调签名 . 如果它们真的可以互换,那么你描述的情况(特别是CoolFoo
的函数)对你的设计来说不是问题 .