不允许导入周期

zer*_*ing 95 go

我有问题

不允许进口周期

看来,当我试图测试我的控制器时.作为输出我有

can't load package: import cycle not allowed
package project/controllers/account
    imports project/controllers/base
    imports project/components/mux
    imports project/controllers/account
import cycle not allowed
package project/controllers/account
    imports project/controllers/base
    imports project/components/mux
    imports project/controllers/account
import cycle not allowed
package project/controllers/account
    imports project/controllers/base
    imports project/components/mux
    imports project/controllers/routes
    imports project/controllers/base
Run Code Online (Sandbox Code Playgroud)

有人能告诉我,如何阅读或理解这个错误?依赖在哪里错了?

jma*_*ney 137

以下是您的第一个导入周期问题的说明.

                  project/controllers/account
                     ^                    \    
                    /                      \
                   /                        \ 
                  /                         \/
         project/components/mux <--- project/controllers/base
Run Code Online (Sandbox Code Playgroud)

你可以用我的坏ASCII图表看是要创建一个导入周期时project/components/mux进口project/controllers/account.由于Go不支持循环依赖,因此import cycle not allowed在编译期间会出现错误.

  • 这个“答案”解释了问题,但没有提供可行的解决方案。 (22认同)
  • 不知怎的,我在java上从来没有遇到过这个问题……为什么我又用Go了? (14认同)
  • 允许使用循环deps会显着增加编译时间,因为每次deps更改时都需要重新编译整个deps圈.拥有圆形deps也是一个沉重的认知负荷,因为它使你更难推理你的程序,并倾向于复杂性. (11认同)
  • 这是我不喜欢Go的原因之一.这只是十几个原因之一. (8认同)
  • 太糟糕了,这只能在编译时显示。浪费了很多时间来重组我的Hole项目,只是为了看看我被禁止做我做过的事... dafug ... (6认同)
  • 这可以通过定义一个自定义接口来解决,通过该接口每个包可以链接到其他包的类型,而不是直接导入它们。 (2认同)
  • 这也是我喜欢Go的原因之一。这只是十几个原因之一。 (2认同)

Jon*_*Lin 73

我刚遇到这个.您可能正在使用包名本身从同一包中访问方法/类型.

这是一个例子来说明我的意思:

在foo.go中:

// foo.go
package foo

func Foo() {...}
Run Code Online (Sandbox Code Playgroud)

在foo_test.go中:

// foo_test.go
package foo

// try to access Foo()
foo.Foo() // WRONG <== This was the issue. You are already in package foo, there is no need to use foo.Foo() to access Foo()
Foo() // CORRECT
Run Code Online (Sandbox Code Playgroud)

  • 这个答案只给出了循环导入的一个实例,并且它是最不复杂的一个,一个导入自身的包。大多数时候,当您遇到此错误时,您会删除许多软件包,了解如何解释该错误将比了解该错误如何发生的一个实例更进一步 (5认同)
  • 在我看来,这是更好的答案.接受的答案同样有效,但除了这种失败的理论之外,没有任何其他解释.@Jonathan Lin的回答然而,完美地解释了这个神秘的错误信息,以及如何对抗它. (4认同)
  • 现在是 2020 年,我建议这应该是更好且可以接受的答案。@堆栈溢出 (4认同)

小智 6

这是一个循环依赖问题。Golang 程序必须是非循环的。在 Golang 中不允许循环导入(即其导入图不得包含任何循环)

假设你的项目go-circular-dependency有 2 个包“包一”&它有“one.go”&“包二”&它有“two.go”所以你的项目结构如下

+--go-circular-dependency    
      +--one    
         +-one.go
      +--two        
         +-two.go
Run Code Online (Sandbox Code Playgroud)

当您尝试执行以下操作时会出现此问题。

第 1 步- 在one.go您导入package two(以下是one.go

package one

import (
    "go-circular-dependency/two"
)

//AddOne is
func AddOne() int {
    a := two.Multiplier()
    return a + 1
}
Run Code Online (Sandbox Code Playgroud)

第 2 步- 在two.go您导入package one(以下是two.go

package two

import (
    "fmt"
    "go-circular-dependency/one"
)

//Multiplier is going to be used in package one
func Multiplier() int {
    return 2
}

//Total is
func Total() {
    //import AddOne from "package one"
    x := one.AddOne()
    fmt.Println(x)
}
Run Code Online (Sandbox Code Playgroud)

在步骤 2 中,您将收到错误“无法加载包:不允许导入循环”(这称为“循环依赖”错误

从技术上讲,这是一个糟糕的设计决策,您应该尽可能避免这种情况,但是您可以“通过隐式接口打破循环依赖”(我个人不推荐,并强烈反对这种做法,因为按照设计 Go 程序必须是非循环的)

尽量保持你的导入依赖浅。当依赖关系图变得更深(即包 x 导入 y,y 导入 z,z 导入 x)时,循环依赖变得更有可能。

有时代码重复也不错,这与 DRY 正好相反(不要重复自己)

因此,在第 2 步中,two.go您不应导入包 1。相反,two.go您应该实际复制AddOne()写入的功能,one.go如下所示。

package two

import (
    "fmt"
)

//Multiplier is going to be used in package one
func Multiplier() int {
    return 2
}

//Total is
func Total() {
    // x := one.AddOne()
    x := Multiplier() + 1
    fmt.Println(x)
}
Run Code Online (Sandbox Code Playgroud)

  • 感谢您的回答,但是由于可维护性,我喜欢 DRY 方法。对我来说,“有时代码重复不是坏主意”并不好,因为如果我在 12 个结构组之间具有通用功能,我必须在每个结构组中编写 12 次,并更新该代码 12 次。 (3认同)

Thu*_*ika 5

您可能已经进口了,

project/controllers/base
Run Code Online (Sandbox Code Playgroud)

在 - 的里面

project/controllers/routes
Run Code Online (Sandbox Code Playgroud)

您之前已经导入过。这是不支持的。