Dependencies 关于如何避免Go中的导入周期,有什么好的建议吗?
我正在做一个为期一个月的围棋项目。好消息是围棋真的很高效。但是经过一个月的开发,我已经有了数千行代码和许多Dependencies 关于如何避免Go中的导入周期,有什么好的建议吗?,dependencies,go,circular-dependency,Dependencies,Go,Circular Dependency,我正在做一个为期一个月的围棋项目。好消息是围棋真的很高效。但是经过一个月的开发,我已经有了数千行代码和许多包。为了避免导入周期对我来说是一个主要问题,每当我遇到导入周期错误时,我都不知道第一次出现问题的地方 Go编译器也只有一个非常简单的注意事项,即始终不足以快速定位问题,例如:main.Go:7:3:import cycle not allowed。它只会帮助您知道哪个文件可能会导致问题,但没有什么比这更深入的了。由于随着代码的增长,import关系变得越来越复杂,我很想知道如何在Go中更有效
包。为了避免导入周期对我来说是一个主要问题,每当我遇到导入周期错误时,我都不知道第一次出现问题的地方
Go编译器也只有一个非常简单的注意事项,即始终不足以快速定位问题,例如:main.Go:7:3:import cycle not allowed
。它只会帮助您知道哪个文件可能会导致问题,但没有什么比这更深入的了。由于随着代码的增长,import
关系变得越来越复杂,我很想知道如何在Go中更有效地避免导入周期。非常感谢您的帮助
go list -f '{{join .Deps "\n"}}' <import-path>
有关go list工具的更多信息。为了补充JML的答案(这有助于“调试”循环引用问题),您可以使用中断这些循环,并结合依赖项注入。对于一个应用程序,我总是尝试遵循的指导原则-请参阅,以获得一个特定于Go的示例-我发现Go的接口“非声明性实现”(即,您不必显式地说类型MyStruct struct implements IfceSomething
)使这非常简单
因此,如果您有包A->B->C->A
,那么您可以在包C中创建InterfaceA
(一些相关的名称,显然比包相关的行为更相关:),并使其依赖于此接口而不是包A,并且确保包A“实现”此接口
然后,您只需要在某一点上提供a到C的具体实现(这里有很多可能性,我通常在主包中“粘合”代码,它了解所有依赖项)
由于导入关系变得越来越复杂,而代码
随着时间的推移,我渴望知道如何更有效地避免导入周期
去吧
另一个选项是可视化项目中的依赖项。这可以通过CLI工具完成。
您可以通过以下方式安装它:
go get -u github.com/kisielk/godepgraph
然后在另一个CLI工具的帮助下,使用它在应用程序中查找导入周期。
使用此工具,您可以可视化包依赖关系:
godepgraph -s path/to/my/package | dot -Tpng -o godepgraph.png
open ./godepgraph.png
要在我的代码中查找周期,请执行以下操作:
除了使用go list工具之外,还可以从体系结构视图确认您已经知道的依赖关系,您需要确保依赖关系树足够深,以便通过构建子组件来了解周期。如果模块中存在导入周期,则应清除存在的周期。应该有足够的模块化(树深度)来无缝地移动这些依赖项
Model -> Field (Uses A) -- Needs to import "System"
Model -> System (Defines A) -- But needs to import "Field"
----------Move type A Struct A.go to top of module----------
----------This is what the Model Dir looks like now---------
Model -> A
Model -> Field
Model -> System
现在,依赖项已被分离,孩子们可以自由地使用。这可能无助于可视化依赖关系,或者是一个很好的基于工具的解决方案,但是再一次,如果您充分地解耦逻辑并构建子组件,那么您应该很快地在循环中收敛。否则,如果您使用的是树可视化工具,我会说这是万不得已的办法,是设计不佳/子组件不足的结果。很好知道,实际上,我甚至不知道go列表。较新版本的go为您提供了有关导入周期来源的更多信息
godepgraph -s path/to/my/package | dot -Tpng -o godepgraph.png
open ./godepgraph.png
Model -> Field (Uses A) -- Needs to import "System"
Model -> System (Defines A) -- But needs to import "Field"
----------Move type A Struct A.go to top of module----------
----------This is what the Model Dir looks like now---------
Model -> A
Model -> Field
Model -> System