【发布时间】:2019-02-20 07:27:59
【问题描述】:
我正在练习编写惯用的 Go 代码,并发现接口应该在使用它们的包中声明,因为它们是隐式的。但是我遇到了这种情况,在第二个包(包 b)中,我想要一个函数来调用包 a 中结构的接收器函数,而不是紧密耦合它。
所以很自然,我在包 b 中声明了一个接口,并带有我想从包 a 调用的函数的签名。问题是这个函数接受某个类型的参数,它是包 a 中声明的接口。由于我不希望包 b 导入包 a,因此我在包 b 中定义了一个接口,其签名与包 a 中存在的签名完全相同。下面的 Playground 链接显示了示例代码。
package main
import (
"fmt"
"log"
)
func main() {
manager := &Manager{}
coach := NewRunnerCoach(manager)
fmt.Println("Done")
}
// package a
type Runner interface {
Run()
}
type Manager struct {
}
func (o *Manager) RegisterRunner(runner Runner) {
log.Print("RegisterRunner")
}
func (o *Manager) Start() {
log.Print("Start")
}
// package b
type RunnerCoach struct {
runner *FastRunner
}
func NewRunnerCoach(registerer runnerRegisterer) *RunnerCoach {
runnerCoach := &RunnerCoach{&FastRunner{}}
registerer.RegisterRunner(runnerCoach.runner)
return runnerCoach
}
type FastRunner struct {
}
func (r *FastRunner) Run() {
log.Print("FastRunner Run")
}
// define ther registerer interface coach is accepting
type runnerRegisterer interface {
RegisterRunner(runner RunnerB)
}
// declaring a new interface with the same signature because we dont want to import package a
// and import Runner interface
type RunnerB interface {
Run()
}
此代码无法编译。所以这里的问题是,我是错误地使用了接口,还是应该在单独的包中定义具体类型,或者最后,对于我要解决的问题,是否有更好的代码模式?
编辑:为了澄清,包 a 和 b 不会相互导入。 main() 代码存在于连接这两者的单独包中。
【问题讨论】: