在Go中修复导入周期 [英] Fixing import cycle in Go

查看:75
本文介绍了在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 accessing action.Register at all, or perhaps action 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 within view, and injected into the View object when it is constructed.
  • You need one or more additional, separate packages to hold the logic used by both the view and action 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. 完全独立的软件包,不引用其他第一方软件包(它们当然可以引用标准库或其他第三方软件包)。

  2. 逻辑软件包其唯一内部依赖项为上述类型1,即完全独立的包。这些程序包不应相互依赖或依赖于下面的类型3。

  3. 接线程序包,主要与逻辑程序包交互,并处理实例化,初始化,配置和注入。的依赖关系。这些可以依赖于其他3类软件包以外的任何其他软件包。您应该需要这种类型的软件包非常少-通常只有一个, main ,但对于更复杂的应用程序,偶尔需要两个或三个。

  1. Wholly self-contained packages, which reference no other first-party packages (they can of course reference the standard library or other third-party packages).
  2. 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.
  3. "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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆