Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I resolve "cannot find module for path X" importing a local Go module?

Tags:

In my Go project, I want to break out some generic functionality into a Go module, separate from the main project. I'm doing this outside of GOPATH in keeping with go's future. I don't want to publish the module on GitHub or anywhere else.

All my attempts to import this module into the main project result in:

cannot find module for path X 

I've run go mod init X in the module's folder. The contents of its go.mod file is:

module X 

Building or installing this module seems to do nothing. I've found no sign of it in $GOPATH/pgk/mod.

I've tried a variety of import statements:

  • import "X"
  • import "../x" (relative path to the module directory)
  • import "../x/X" (path to the directory + module name)

Help!

like image 990
Inigo Avatar asked Aug 31 '18 23:08

Inigo


People also ask

How do I run a Go module?

Open a command prompt and cd to your home directory. Create a greetings directory for your Go module source code. Start your module using the go mod init command. Run the go mod init command, giving it your module path -- here, use example.com/greetings .

Where do Go modules get installed?

All downloaded modules are cached locally in your $GOPATH/pkg/mod directory by default. If you import a package to your project without downloading it first using go get , the latest tagged version of the module providing that package will be installed automatically and added to your go.

Where are Go module dependencies installed?

Modules may be downloaded directly from version control repositories or from module proxy servers. A module is identified by a module path, which is declared in a go. mod file, together with information about the module's dependencies. The module root directory is the directory that contains the go.

What is a module in Go?

A module is a collection of Go packages stored in a file tree with a go. mod file at its root. The go. mod file defines the module's module path, which is also the import path used for the root directory, and its dependency requirements, which are the other modules needed for a successful build.


2 Answers

So you wrote a Go "library" module X which:

  • you don't want to publish on GitHub or elsewhere
  • you want to import and use in your project (the "main" module).

Use a replace directive along with require

In your main module's go.mod, add the following lines:

require "X" v0.0.0 replace "X" v0.0.0 => "{local path to the X module}" 

The path should point to the root directory of X. It can be absolute or relative.

To import package util from module X:

import "X/util" 

(You don't import modules. You import packages from modules.)


Explanation

Go's module functionality is designed for publicly published modules. Normally, a module's name is both its unique identifier and the path to its public repo. When your go.mod declares a module dependency with the require directive, Go will automatically find and retrieve the specified version of the module at that path.

If, for example, your go.mod file contains require github.com/some/dependency v1.2.3, Go will retrieve the module from GitHub at that path. But if it contains require X v0.0.0, "X" isn't an actual path and you will get the error cannot find module for path X.

The replace directive allows you to specify a replacement path for a given module identifier and version. There are many reasons you'd want to do this, such as to test changes to a module before pushing them to the public repo. But you can also use it to bind a module identifier to local code you don't ever intend to publish.

More details in the Go Modules documentation:

  • Can I work entirely outside of VCS on my local filesystem?
  • When should I use the replace directive?

Hope this helps.

like image 153
Hamza Anis Avatar answered Oct 23 '22 05:10

Hamza Anis


If you don't want to use Go modules, you don't need to. As of Go v1.13, by default, go modules are used. Therefore, you need to tell explicitly if you don't want to do this.

Example:

main.go:

package main  import (     "fmt"      "./pakk" )  func main() {     fmt.Println("Hello" + pakk.World()) } 

pakk/pakk.go:

package pakk  func World() string {     return " world" } 

In this case, running go run main.go will output

build command-line-arguments: cannot find module for path .../pakk 

but running

GO111MODULE=off go run main.go 

will output

Hello world 
like image 27
Csongor Halmai Avatar answered Oct 23 '22 06:10

Csongor Halmai