1

How can I analyze which source file is causing the "import cycle not allowed" problem? The error message isn't clear enough to allow me to solve the problem:

package command-line-arguments
    imports app.exap/i8/internal
    imports app.exap/i8/internal/data/retrieves
    imports app.exap/i8/internal/integration/datastore
    imports app.exap/i8/internal/objects/modules
    imports app.exap/i8/internal/data
    imports app.exap/i8/internal/integration/datastore: import cycle not allowed
package command-line-arguments
    imports app.exap/i8/internal
    imports app.exap/i8/internal/data/retrieves
    imports app.exap/i8/internal/integration/datastore
    imports app.exap/i8/internal/objects/modules
    imports app.exap/i8/internal/data
    imports app.exap/i8/internal/objects/modules: import cycle not allowed
jub0bs
  • 60,866
  • 25
  • 183
  • 186
Marwan Jaber
  • 611
  • 11
  • 27
  • Related: https://stackoverflow.com/questions/16168601/any-good-advice-about-how-to-avoid-import-cycle-in-go – jub0bs Jun 06 '21 at 06:47

1 Answers1

7

The problem cannot be ascribed to a single source file, simply because an import cycle typically involves multiple source files from different packages.

You can glean valuable information from the error message, though: your project seems to suffer from two distinct import cycles (a 2-cycle and a 3-cycle) involving three packages:

enter image description here

To break those cycles, you first need to decide which edges of the cycles should be eliminated. It's difficult for me to give you definite guidance about this, though, as the best edge to eliminate is highly dependent on the context of your project.

However, a good rule of thumb for avoiding import cycles in Go is that high-level packages shouldn't depend on lower-level packages. Accordingly, you most likely do not want app.exap/i8/internal/data to depend on

  • either app.exap/i8/internal/integration/datastore
  • or app.exap/i8/internal/objects/modules.

Once you've decided which two edges to eliminate, simply identify which source file(s) of the importing packages contain the offending import declarations and find a way to refactor your code so as to remove them.

jub0bs
  • 60,866
  • 25
  • 183
  • 186
  • 1
    Can you expound on your point about high level packages not depending on low level packages? I’ve always done it the other way around. For example my core models I considered to be pretty low level, and they have nearly 0 dependencies, which allows them to be imported by everything else without the risk of an import cycle. Thanks! – Clark McCauley Jun 06 '21 at 14:33
  • @ClarkMcCauley Go projects, incl. the core library, tend to be organised in a particular way: generality tends to "point up" and specificity tends to "point down". More concretely, subpackages usually provide more specific, low-level functionalities than their superpackages do. See `encoding` and its subpackages, `crypto` and its subpackages, etc. Why do dependency arrows tend not to "point down", then? I see a parallel with the [dependency-inversion principle](https://en.wikipedia.org/wiki/Dependency_inversion_principle): you rarely want high-level packages to depend on low-level packages. – jub0bs Jun 06 '21 at 15:46