周期性进口和缺乏仿制药引起头痛

时间:2018-12-03 01:06:56

标签: go

说我在golang中有这两个文件:

// main/a/a.go
import "main/b"

type Model struct {
    ID         int    `json:"id"`
    Me         int    `json:"me"`
    You        int    `json:"you"`
}

func zoom(v b.Injection){

}

func Start(){
  // ...
}

然后第二个文件如下:

// main/b/b.go
import "main/a"

type Injection struct {
    ModelA a.Model
}


func GetInjection() Injection {
    return Injection{
        ModelA: a.Start(),
    }
}

如您所见,这些是循环导入,每个文件都导入另一个。 因此,我需要使用第3个文件,并让这两个文件导入第3个文件。

但是我真的在努力获得此功能并避免循环导入。

我的第一步是将Injection类型移动到第3个文件中:

   // main/c/c.go

    type Injection struct {
        ModelA interface{} // formerly a.Model
    }

所以现在是这样:

a imports c
b imports a,c

因此不再有循环,但是问题是我不知道如何在a.Model中为c.go创建接口?出于正常原因,我上面使用的空interface{}无效。

如何用这两个原始文件解决此循环导入问题?

1 个答案:

答案 0 :(得分:2)

如果要将它们放入单独的包装中,则不能在同一包装中包含Modelzoom(),因为zoom()指的是Injection和{{ 1}}是指Injection

因此,可能的解决方案是将Model放入软件包Model,将a放入软件包zoom(),并将b放入软件包Injectionc可以引用c.Injectiona.Model可以引用b.zoom()。里面没有圆圈:

c.Injection

我假设您的真实代码中还有其他引用可能会阻止此引用的工作,但您可以在软件包之间移动“填充”,也可以将其分解为更多。

此外,如果事物紧密结合在一起,那么您应该真正考虑将它们放入同一包装中,这样就没有问题可以解决。

解决循环导入问题的另一种方法是引入接口。例如。如果您的 b.zoom() --------> c.Injection ---------> a.Model 函数不会引用zoom(),则包含InjectionModel的程序包将不需要引用zoom()的程序包。

检查Injectionzoom()有什么关系。如果那是方法调用,那已经很好。如果没有,请向Injection添加方法。然后,您可以在Injection的程序包中定义一个接口,其中包含需要调用的方法zoom(),并将其参数类型更改为此接口。在Go中实现接口是隐式的,没有意图的声明。因此,您可以删除参数类型中的引用,仍然可以将zoom()的值传递给Injection

也相关,请检查Dave Cheney's thoughts about organizing code

  

我认为代码应该按照软件包提供的内容(而不是包含的内容)组织到软件包名称中。这有时可能很微妙,但通常不是。

     

例如,http提供http客户端和服务器。

     

作为反例,软件包utils是一个不好的名字,是的,它提供了实用程序,但您不知道名称是什么,实际上,此软件包是根据其包含的内容来命名的。

     

如果您的项目是一个库,则它应该包含一个软件包(不包括示例和可能的实用程序命令),如果它包含更多的软件包,则表明该库正试图做太多事情。

     

默认情况下,最好避免使用多个程序包,只有在有明确的关注点分离时,才按程序包拆分代码。以我的经验,复杂和可能是圆形包装结构的许多挫败是项目中包装太多的结果。