Cykl importu jest niedozwolony


149

Mam problem z

cykl importu niedozwolony

Pojawia się, gdy próbuję przetestować mój kontroler. Jako wyjście mam

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

Czy ktoś może mi powiedzieć, jak czytać lub rozumieć ten błąd? Gdzie jest zależność?


16
Na accountimport pakietów basepakiet, który importuje muxpakiet, który importuje accountpakiet. To cykliczny zestaw zależności importu, co jest niedozwolone. Wygląda na to masz inny cykl, jak również, baseimportu mux, których przywóz routes, który importuje base.
Amit Kumar Gupta

Odpowiedzi:


180

Oto ilustracja Twojego pierwszego problemu z cyklem importu.

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

Jak widać na moim złym wykresie ASCII, podczas project/components/muximportu tworzysz cykl importu project/controllers/account. Ponieważ Go nie obsługuje zależności cyklicznych, import cycle not allowedbłąd pojawia się podczas kompilacji.


11
Tak źle, że pojawia się tylko podczas kompilacji. Zmarnowałem dużo czasu na restrukturyzację mojego projektu dołka tylko po to, aby zobaczyć, że nie wolno mi robić tego, co zrobiłem ... dafug ...
C4d

39
To jeden z powodów, dla których nie lubię Go. A to tylko jeden z wielu powodów.
tom10271

19
Zezwolenie na cykliczne deps znacznie wydłużyłoby czas kompilacji, ponieważ cały twój krąg deps musiałby być rekompilowany za każdym razem, gdy zmienił się jeden z deps. Posiadanie okrągłych deps jest również dużym obciążeniem poznawczym, ponieważ utrudnia rozumowanie na temat programu i ma tendencję do złożoności.
jmaloney

którego lintera używasz, nie widzę żadnego lintingu w kodzie vs
Gopherine

Widzę ten błąd podczas uruchamiania aplikacjiwatcher
R Sun

114

Właśnie to spotkałem. Możesz uzyskiwać dostęp do metody / typu z tego samego pakietu, używając samej nazwy pakietu.

Oto przykład ilustrujący, co mam na myśli:

W foo.go:

// foo.go
package foo

func Foo() {...}

W 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

14
Moim zdaniem to lepsza odpowiedź. Przyjęta odpowiedź jest równie ważna, ale nie wyjaśnia niczego innego niż teoria takiego niepowodzenia. Jednak odpowiedź @Jonathan Lin doskonale wyjaśnia ten tajemniczy komunikat o błędzie i wyjaśnia, jak z nim walczyć.
fantasitcalbeastly

Jest rok 2020 i proponuję, aby to była lepsza i akceptowana odpowiedź. @stackoverflow
Louie Miranda

3

Mogłeś zaimportować,

project/controllers/base

w środku

project/controllers/routes

Już wcześniej importowałeś. To nie jest obsługiwane.


2

Jest to kwestia zależności cyklicznych. Programy Golang muszą być acykliczne. W Golang import cykliczny nie jest dozwolony (czyli jego wykres importu nie może zawierać żadnych pętli)

Powiedzmy, że Twój projekt go-circular-dependencyma 2 pakiety „pakiet pierwszy” i „jeden.go” i „pakiet drugi” oraz „dwa.go” Więc struktura projektu jest następująca

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

Ten problem występuje, gdy próbujesz wykonać coś takiego jak śledzenie.

Krok 1 - Podczas one.goimportu package two(poniżej one.go)

package one

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

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

Krok 2 - W two.goimporcie package one(poniżej 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)
}

W kroku 2 zostanie wyświetlony komunikat o błędzie „nie można załadować pakietu: cykl importu niedozwolony” (jest to nazywane błędem „zależności cykliczne )

Technicznie rzecz biorąc, jest to zła decyzja projektowa i powinieneś jej unikać tak bardzo, jak to tylko możliwe, ale możesz "przełamać zależności cykliczne przez niejawne interfejsy" (osobiście nie polecam i bardzo odradzam tej praktyki, ponieważ z założenia programy Go muszą być acykliczne )

Staraj się, aby zależność od importu była niewielka. Gdy wykres zależności staje się głębszy (tj. Pakiet x importuje y, y importuje z, z importuje x), wówczas bardziej prawdopodobne stają się zależności cykliczne.

Czasami powtórzenie kodu nie jest złym pomysłem, co jest przeciwieństwem DRY (nie powtarzaj się)

Dlatego w kroku 2, który jest w two.gośrodku, nie powinieneś importować pierwszego pakietu. Zamiast tego two.gopowinieneś faktycznie powielić funkcjonalność AddOne()napisaną w one.gonastępujący sposób.

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)
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.