Search code examples
gogo-modules

Problem with modules and importing folders


I have some problems with how Go importing and modules works. I have a project with this structure:

My-Project
|- Program 1
   |- main.go
   |- go.mod
|- Program 2
   |- main.go
   |- go.mod
|- Support
   |- go_file.go

The two programs have different module "definition". I need to include the "Support" folder, which is shared between the two programs. I tried

import "My-Project/Support" 

inside Program1's main.go, but this is not working, because Support can’t be resolved. How can I do it?


Solution

  • As given, your Support/go_file.go is not in any module so it's not importable using Go modules.

    Either use a single module for all three packages or use three separate modules (i.e. put Support in it's own module). You could also use sub-modules.

    Single module:

    For a single module you'd do something like:

    └── My-Project
        ├── go.mod
        ├── Program\ 1
        │   └── main.go
        ├── Program\ 2
        │   └── main.go
        └── Support
            └── go_file.go
    

    And the project level go.mod would be something like:

    module github.com/My-Name/My-Project
    

    (substitute with appropriate module name) and then both main packages would import the support package with:

    import "github.com/My-Name/My-Project/Support"
    

    Note Go packages normally do not start with capitals like this.

    More idiomatic for such a setup with a single repository which mixes packages and commands is a layout that puts commands into a cmd subdirectory (e.g. see the golang.org/x/tools layout). This would look something like this:

    └── My-Project
        ├── cmd
        │   ├── program1
        │   │   └── main.go
        │   └── program2
        │       └── main.go
        ├── go.mod
        ├── internal
        │   └── support
        │       └── support.go
        └── other-package
            └── some-other-package.go
    

    Here the support package is in an internal sub-directory which makes it non-importable from outside My-Project where-as the other-package is importable by anyone.

    Again, go.mod would define the module name which sets the prefix to be used for all import statements.

    Separate modules:

    To use separate modules you'd do something like:

    └── My-Project
        ├── Program\ 1
        │   ├── go.mod
        │   └── main.go
        ├── Program\ 2
        │   ├── go.mod
        │   └── main.go
        └── Support
            ├── go_file.go
            └── go.mod
    

    Here My-Project/Program 1/go.mod would be something like:

    module "github.com/My-Name/My-Project/Program 1"
    
    require (
            github.com/My-Name/My-Project/Support
    )
    

    The imports would be the same as for the single module example. Similarly for Program 2. For Support/go.mod it'd look something like:

    module github.com/My-Name/My-Project/Support
    

    For local development you'll probably also want/need a replace directive in each program's go.mod to use your local working copy of the support module (go mod edit -replace github.com/My-Name/My-Project/Support=../Support should add this).