【问题标题】:Cyclic dependencies between sources of a package包源之间的循环依赖
【发布时间】:2018-10-16 07:37:04
【问题描述】:

假设您有一个包mypack,其中包含两个源文件mypack/a.gomypack/b.go。这两个源文件相互依赖,但 Go 编译器不会抱怨。如果你把这个包分成两个,apack/a.gobpack/b.go,Go 编译器会说import cycle not allowed

我对如何处理包依赖项的理解是编译器将构建导入图。该图被分析并以某种方式(我很想了解执行此操作的算法!)计算编译顺序。如果图中有循环,则无法计算顺序,因此编译器会报错。

我不明白的是,Go 编译器如何能够解决包源之间的依赖关系,但无法解决包之间的依赖关系。如果这两个来源相互依赖,那么您必须做一些疯狂的杂技并以某种方式同时编译它们。

谁能帮我解决这个问题?

【问题讨论】:

  • 一个包被编译为一个单元,不管使用了多少源文件。这不应该真的那么神秘。
  • 此外,您断言“如果有循环则无法计算订单”是完全错误的。计算这些东西是微不足道的——许多语言都这样做。不过,Go 禁止这样做是出于政策考虑,而不是因为这是不可能的。
  • @Flimzy 您的 cmets 值得真正回应。

标签: go compiler-errors compilation package


【解决方案1】:

[...] Go 编译器如何能够解决包源之间的依赖关系,但不能解决包之间的依赖关系。如果这两个来源相互依赖,那么您必须做一些疯狂的杂技并以某种方式同时编译它们。

问题是基于对 Go 代码的结构和编译方式的错误假设:源文件确实 根据定义具有依赖关系.一个包具有依赖项(所有来自其所有源文件的导入)。依赖项是包(不是源文件)。要编译一个包,所有依赖项都必须在之前编译开始。

您真的必须停止考虑源文件。源文件(几乎)对 Go 代码的编译方式没有任何意义。一个包的源代码可能由一个或多个源文件组成,这基本上是源文件进入编译 Go 代码的唯一点。一切相关的东西都只围绕包和包:编译包、导入包等。

(仅出于完整性考虑:构建标签在源代码级别工作,包初始化可以依赖于源代码组织,通过手动调用 gc,您可以做的不仅仅是通过 go 工具。)

【讨论】:

    【解决方案2】:

    无论使用多少源文件,一个包都被编译为一个单元。这不应该真的那么神秘。

    此外,您断言“如果存在循环,则无法计算顺序”是完全错误的。计算这些东西很简单——许多语言都这样做。不过,Go 禁止这样做,因为它会导致代码的紧密耦合,以及难以理解的代码,而不是因为它不可能。

    【讨论】:

    • 你还没有真正回答我的问题。 Go 编译器不能简单地连接两个源文件并将它们编译为一个大单元,因为存在循环依赖关系。编译器不能将一个文件放在另一个文件之前。
    • 尽管如此,编译器仍然能够弄清楚。这是我的问题
    猜你喜欢
    • 2021-04-16
    • 2018-08-19
    • 2021-09-27
    • 1970-01-01
    • 2019-12-04
    • 2017-12-12
    • 2019-02-04
    • 2014-11-10
    • 2021-04-23
    相关资源
    最近更新 更多