Цикл импорта не разрешен

138

У меня проблема с

цикл импорта не разрешен

Похоже, когда я пытаюсь протестировать свой контроллер. На выходе у меня есть

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

Может кто подскажет, как прочитать или понять эту ошибку? Где неправильная зависимость?

zero_coding
источник
13
В accountимпорте пакета В baseпакете, который импортирует muxпакет, который импортирует accountпакет. Это циклический набор зависимостей импорта, который недопустим. Похоже, у вас тоже есть другой цикл: baseимпорт mux, какой импорт routes, какой импорт base.
Амит Кумар Гупта

Ответы:

172

Вот иллюстрация вашей первой проблемы цикла импорта.

                  project/controllers/account
                     ^                    \    
                    /                      \
                   /                        \ 
                  /                         \/
         project/components/mux <--- project/controllers/base

Как вы можете видеть на моей плохой диаграмме ASCII, вы создаете цикл project/components/muxимпорта при импорте project/controllers/account. Поскольку Go не поддерживает циклические зависимости, вы получите import cycle not allowedошибку во время компиляции.

jmaloney
источник
11
Так плохо, что это проявляется только при компиляции. Потратил много времени на реструктуризацию моего проекта скважины, просто чтобы увидеть, что мне не разрешено делать то, что я делал ... черт возьми ...
C4d
36
Это одна из причин, почему я не люблю го. И это лишь одна из десятков причин.
tom10271 02
13
Разрешение круговой deps значительно увеличит время компиляции, поскольку весь ваш круг deps нужно будет перекомпилировать каждый раз при изменении одной из deps. Круговая глубина также является тяжелой когнитивной нагрузкой, поскольку затрудняет рассуждение о вашей программе и имеет тенденцию к сложности.
jmaloney 02
какой линтер вы используете, я не вижу линтинга по коду vs
Gopherine
Я вижу эту ошибку при запуске приложенияwatcher
R Вс,
100

Я только что столкнулся с этим. Вы можете получить доступ к методу / типу из того же пакета, используя само имя пакета.

Вот пример, чтобы проиллюстрировать, что я имею в виду:

В foo.go:

// foo.go
package foo

func Foo() {...}

В 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
Джонатан Лин
источник
6
На мой взгляд, это лучший ответ. Принятый ответ так же верен, но не объясняет ничего, кроме теории такой неудачи. Однако ответ @Jonathan Lin прекрасно объясняет это загадочное сообщение об ошибке и способы борьбы с ней.
fantasitcalbeastly
3

Возможно, вы импортировали,

project/controllers/base

внутри

project/controllers/routes

Вы уже импортировали раньше. Это не поддерживается.

Тушара Буддхика
источник
2

Это проблема "круговой зависимости"

Программы Golang должны быть ацикличными. В Golang циклический импорт не разрешен (то есть его граф импорта не должен содержать никаких циклов)

Допустим, ваш проект "go-round-dependency" имеет 2 пакета "package one" и имеет "one.go" и "package two" и имеет "two.go". Итак, структура вашего проекта следующая

+--go-circular-dependency    
      +--one    
         +-one.go
      +--two        
         +-two.go

Эта проблема возникает, когда вы пытаетесь сделать что-то вроде следующего.

Шаг 1. В «one.go» вы импортируете «второй пакет» (далее «one.go»)

package one

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

//AddOne is
func AddOne() int {
    a := two.Multiplier()
    return a + 1
}

Шаг 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)
}

На шаге 2 вы получите сообщение об ошибке «не удается загрузить пакет: цикл импорта не разрешен» (это называется ошибкой «Циклическая зависимость» ).

С технической точки зрения это плохое дизайнерское решение, и вам следует избегать этого как можно чаще, но вы можете «нарушить циклические зависимости с помощью неявных интерфейсов» (я лично не рекомендую и очень не рекомендую эту практику, потому что по дизайну программы Go должны быть ацикличными. )

Старайтесь, чтобы ваша зависимость импорта была невысокой. Когда граф зависимостей становится глубже (т. Е. Пакет x импортирует y, y импортирует z, z импортирует x), круговые зависимости становятся более вероятными.

Иногда повторение кода - неплохая идея, что прямо противоположно DRY (не повторяйтесь)

Таким образом, на шаге 2, который находится в "two.go", вы не должны импортировать первый пакет. Вместо этого в «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)
}
Сачин Раут
источник