Go 周期性进口和缺乏仿制药导致头痛
假设我在golang有两个文件:Go 周期性进口和缺乏仿制药导致头痛,go,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(){ // ... } 然后第二个文件看起来像: // mai
// 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(),
}
}
a imports c
b imports a,c
如您所见,这些是循环导入,每个文件导入另一个文件。
所以我需要使用第三个文件,让这两个文件导入第三个文件
但我真的在为如何获得这一功能和避免循环导入而苦苦挣扎
我的第一步是将注入
类型移动到第三个文件中:
// main/c/c.go
type Injection struct {
ModelA interface{} // formerly a.Model
}
现在看起来是这样的:
// main/b/b.go
import "main/a"
type Injection struct {
ModelA a.Model
}
func GetInjection() Injection {
return Injection{
ModelA: a.Start(),
}
}
a imports c
b imports a,c
因此没有更多的循环,但是问题是我不知道如何在c.go
中为a.Model
创建接口?出于正常原因,我上面使用的空接口{}
不起作用
如何解决这两个原始文件的循环导入问题?如果要将它们放入单独的包中,不能将
Model
和zoom()
放在同一个包中,因为zoom()
指的是Injection
和Injection
指的是Model
因此,一个可能的解决方案是将模型
放入包a
,zoom()
放入包b
,并注入包c
c.Injection
可参考a.Model
,b.zoom()
可参考c.Injection
。这里面没有圆圈:
b.zoom() --------> c.Injection ---------> a.Model
我假设在您的实际代码中还有其他引用,这些引用可能会阻止此操作,但您可以在包之间移动“东西”,或者将其分解为更多内容
同样,如果事情是“紧”的,那么你应该考虑把它们放在同一个包中,这样就没有问题要解决了。
解决循环导入问题的另一种方法是引入接口。例如,如果您的
zoom()
函数不会引用Injection
,则包含Model
和zoom()
的包将不需要引用Injection
的包
检查zoom()。如果这是方法调用,那么已经很好了。如果没有,请将方法添加到注入
。然后,您可以在zoom()
的包中定义一个包含zoom()
需要调用的方法的接口,并将其参数类型更改为此接口。在Go中实现接口是隐式的,没有意图声明。因此,您可以删除参数类型中的引用,但仍然可以将Injection
值传递到zoom()
此外,请检查:
我认为代码应该按照包提供的内容而不是包含的内容组织成包名。这有时是微妙的,但通常不是
例如,http提供http客户端和服务器
作为一个反例,包utils是一个糟糕的名称,是的,它提供了实用程序,但您不知道名称中的内容,实际上这个包是根据它包含的内容命名的
如果您的项目是一个库,它应该包含一个包(不包括示例和可能的实用程序命令),如果它包含更多的包,这表明库正在尝试做太多的事情
默认情况下,更倾向于避免多个包,只有在关注点明确分离的情况下,才按包分割代码。根据我的经验,复杂的、可能是循环的包结构的许多挫折都是由于项目中包太多造成的
有没有一个很好的理由首先将它们放在不同的包中?当使用单个软件包时,没有问题。@icza是的,不同的软件包,因为涉及到更多的文件,我只是尽可能地将其浓缩。啊,我想我必须把所有东西都放在同一个软件包中,在同一个文件夹中有20多个文件,哈哈,该死的名称空间,这太糟糕了,这不是你的错,戈兰fault@AlexanderMills我认为不允许循环导入是为了快速编译,但如果应用正确,可能会导致更干净/更符合逻辑的结构。它还可以帮助您更容易地理解包/模块的依赖关系。