任何关于如何避免在Go中导入循环的好build议?

我正在做一个Go项目一个月。 好的是Go非常高效。 但经过一个月的发展,我已经有了数千行代码和许多packages 。 为了避免导入周期对我来说是一个主要的问题,任何时候我有一个导入周期的错误,我不知道这个问题可能在第一时间。

Go编译器也只有非常简单的通知,总是不够好,不能像以下情况main.go:7:3: import cycle not allowed定位问题: main.go:7:3: import cycle not allowed 。 它只会帮助你知道哪个文件可能导致问题,但没有更深层次的。 由于在代码增长的同时, import关系变得越来越复杂,所以我很想知道如何在Go中更有效地避免导入循环。 任何帮助深表感谢。

 go list -f '{{join .Deps "\n"}}' <import-path> 

如果<import-path>为空,将在<import-path>或当前目录中显示包的导入依赖关系。 另外

 go list -f '{{join .DepsErrors "\n"}}' <import-path> 

希望在你的情况下显示一些有用的信息。 另见输出

 go help list 

获取有关go list工具的更多信息。

为了补充jnml的答案(这有助于“debugging”循环引用问题),可以使用依赖倒置来打破这些循环,再加上dependency injection。 对于一个应用程序,我总是试图遵循Clean架构的指导原则 – 请参阅Go-specific示例 – 我发现Go的接口的“非声明性实现”(也就是说,您不必明确地说type MyStruct struct implements IfceSomething )使得这非常简单。

因此,如果你有软件包A -> B -> C -> A ,你可以在软件包C中创buildInterfaceA (一些相关的名字,很明显,与软件包相关的行为相关),并且依赖于这个接口而不是包A,并确保包A“实现”此接口。

那么你只需要在某个时候提供一个具体的A到C的实现(在这里有许多可能性,我通常在知道所有依赖关系的主包中做这个“粘合”代码)。