在Go中修复导入周期 [英] Fixing import cycle in Go
问题描述
所以我要解决这个导入周期。我有以下模式:
So I have this import cycle which I'm trying to solve. I have this following pattern:
view/
- view.go
action/
- action.go
- register.go
总体思路是执行操作在视图上,并由视图执行:
And the general idea is that actions are performed on a view, and are executed by the view:
// view.go
type View struct {
Name string
}
// action.go
func ChangeName(v *view.View) {
v.Name = "new name"
}
// register.go
const Register = map[string]func(v *view.View) {
"ChangeName": ChangeName,
}
然后在view.go中调用:
And then in view.go we invoke this:
func (v *View) doThings() {
if action, exists := action.Register["ChangeName"]; exists {
action(v)
}
}
但是这会导致一个周期,因为View依赖于Action包,反之亦然。如何在此周期内解决
?
But this causes a cycle because View depends on the Action package, and vice versa. How can I solve this cycle? Is there a different way to approach this?
推荐答案
导入周期表明从根本上来说是错误的设计。广义上讲,您正在查看以下其中一项:
An import cycle indicates a fundamentally faulty design. Broadly speaking, you're looking at one of the following:
- 您正在混合担忧。也许
视图
根本不应该访问action.Register
,或者也许action
不应该负责更改视图的名称(或两者都更改)。似乎最有可能。 - 您要依赖固结,而您应该依赖接口并注入固结。例如,它可以直接在
view
action.Register 的视图。 >,并在构造View
对象时注入。 - 您需要一个或多个其他独立的软件包来保存逻辑由
视图
和action
程序包使用,但是两者都不调用。
- You're mixing concerns. Perhaps
view
shouldn't be accessingaction.Register
at all, or perhapsaction
shouldn't be responsible for changing the names of views (or both). This seems the most likely. - You're relying on a concretion where you should be relying on an interface and injecting a concretion. For example, rather than the view accessing
action.Register
directly, it could call a method on an interface type defined withinview
, and injected into theView
object when it is constructed. - You need one or more additional, separate packages to hold the logic used by both the
view
andaction
packages, but which calls out to neither.
通常来说,您想要设计一个应用程序,以便拥有三种基本类型的软件包:
Generally speaking, you want to architect an application so that you have three basic types of packages:
- 完全独立的软件包,不引用其他第一方软件包(它们当然可以引用标准库或其他第三方软件包)。
- 逻辑软件包其唯一内部依赖项为上述类型1,即完全独立的包。这些程序包不应相互依赖或依赖于下面的类型3。
- 接线程序包,主要与逻辑程序包交互,并处理实例化,初始化,配置和注入。的依赖关系。这些可以依赖于其他3类软件包以外的任何其他软件包。您应该需要这种类型的软件包非常少-通常只有一个,
main
,但对于更复杂的应用程序,偶尔需要两个或三个。
- Wholly self-contained packages, which reference no other first-party packages (they can of course reference the standard library or other third-party packages).
- Logic packages whose only internal dependencies are of type 1 above, i.e., wholly self-contained packages. These packages should not rely on each other or on those of type 3 below.
- "Wiring" packages, which mostly interact with the logic packages, and handle instantiation, initialization, configuration, and injection of dependencies. These can depend on any other package except for other type 3 packages. You should need very, very few packages of this type - often just one,
main
, but occasionally two or three for more complex applications.
这篇关于在Go中修复导入周期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!