Import cycle not allowed

Go

Go Problem Overview


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?

Go Solutions


Solution 1 - Go

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.

Solution 2 - Go

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.

Solution 3 - Go

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

Solution 4 - Go

You may have imported,

project/controllers/base

inside the

project/controllers/routes

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

Solution 5 - Go

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.

Solution 6 - Go

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'

Solution 7 - Go

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionsoftshipperView Question on Stackoverflow
Solution 1 - GojmaloneyView Answer on Stackoverflow
Solution 2 - GoJonathan LinView Answer on Stackoverflow
Solution 3 - GoSachin RautView Answer on Stackoverflow
Solution 4 - GoThushara BuddhikaView Answer on Stackoverflow
Solution 5 - Gosaurabh2226View Answer on Stackoverflow
Solution 6 - GosiddhusinghView Answer on Stackoverflow
Solution 7 - GobitbuoyView Answer on Stackoverflow