softshipper
softshipper

Reputation: 34081

Import cycle not allowed

I have a problem with

import cycle not allowed

It appears when I am trying to test my controller. Here is the output:

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

How do I read or understand this error? Where is the dependency wrong?

Upvotes: 266

Views: 343714

Answers (8)

punith ck punith
punith ck punith

Reputation: 121

Reason for import cycle has been mentioned in above answers. I was facing import cycle issue for built-in lib while running a command go build -mod vendor

Ex:
...
...
imports github.com/aws/aws-sdk-go/aws
    imports net/http
    imports crypto/tls
    imports crypto/ecdsa
    imports crypto/elliptic
    imports crypto/internal/nistec
    imports crypto/elliptic: import cycle not allowed

...
...
    imports fmt
    imports errors
    imports internal/reflectlite
    imports runtime
    imports internal/abi
    imports internal/goarch
    imports bytes
    imports errors: import cycle not allowed

It was solved by uninstalling golang and reinstalling it. I think I didnt install the golang correctly before. Thanks for the hint in https://bytemeta.vip/repo/fyne-io/fyne/issues/3089. I couldnt give credits to that person there but mentioning here. Thanks.

Upvotes: 3

bitbuoy
bitbuoy

Reputation: 393

Error The error results from having two modules importing each other simultaneously.

Module A importing Module B
Module B importing Module A

Solution Find a way to make the two way imports a one way import.

Upvotes: 5

siddhusingh
siddhusingh

Reputation: 1868

Sometimes you give the same module name using command ' go mod init x/y/z' and you have the same import as well. This was very hard to solve at least for me. Just give any meaningful name to your mod e.g, 'go mod init sid'

Upvotes: 1

Jonathan Lin
Jonathan Lin

Reputation: 20704

I just encountered this. You may be accessing a method/type from within the same package using the package name itself.

Here is an example to illustrate what I mean:

In foo.go:

// foo.go
package foo

func Foo() {...}

In 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

Another common cause of circular dependency is shown in this answer.

Unlike JavaScript, Go has low tolerance for circular dependencies, which is both a good and a bad thing.

Upvotes: 195

jmaloney
jmaloney

Reputation: 12300

Here is an illustration of your first import cycle problem.

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

As you can see with my bad ASCII chart, you are creating an import cycle when project/components/mux imports project/controllers/account. Since Go does not support circular dependencies you get the import cycle not allowed error during compile time.

Upvotes: 307

saurabh2226
saurabh2226

Reputation: 33

I got another solution for this.

My case

  1. I found out that I had not run the command : go mod init <module_name> before starting to work on the project.

  2. Later I was trying to import the "mux" package go get github/gorilla/mux and then I was getting the error "Import cycle not allowed".

Check if you have initialized a module( the command mentioned in pt 1.) if required in the directory that you are working. Then try running the script.

Upvotes: 2

Sachin Raut
Sachin Raut

Reputation: 338

This is a circular dependency issue. Golang programs must be acyclic. In Golang cyclic imports are not allowed (That is its import graph must not contain any loops)

Lets say your project go-circular-dependency have 2 packages "package one" & it has "one.go" & "package two" & it has "two.go" So your project structure is as follows

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

This issue occurs when you try to do something like following.

Step 1 - In one.go you import package two (Following is one.go)

package one

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

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

Step 2 - In two.go you import package one (Following is 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)
}

In Step 2, you will receive an error "can't load package: import cycle not allowed" (This is called "Circular Dependency" error)

Technically speaking this is bad design decision and you should avoid this as much as possible, but you can "Break Circular Dependencies via implicit interfaces" (I personally don't recommend, and highly discourage this practise, because by design Go programs must be acyclic)

Try to keep your import dependency shallow. When the dependency graph becomes deeper (i.e package x imports y, y imports z, z imports x) then circular dependencies become more likely.

Sometimes code repetition is not bad idea, which is exactly opposite of DRY (don't repeat yourself)

So in Step 2 that is in two.go you should not import package one. Instead in two.go you should actually replicate the functionality of AddOne() written in one.go as follows.

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)
}

Upvotes: 17

Thushara Buddhika
Thushara Buddhika

Reputation: 1820

You may have imported,

project/controllers/base

inside the

project/controllers/routes

You have already imported before. That's not supported.

Upvotes: 5

Related Questions