How to import local packages in Golang
When requiring packages in your go.mod
file, you either have to specify a relative path that points to a directory within GOPATH
; or, you need to specify a URL under which the package may be downloaded.
Sadly it’s not possible to directly specify a path relative to the current working directory. This is a somewhat uncanny limitation, since it implicitly prevents the arguably most simple importing mechanism of importing packages from local directories (such as subdirectories of the project).
For example, consider the following hello-golang
project
mkdir hello-golang
cd hello-golang
go mod init friedrichkurz.me/hello-golang
go mod tidy
mkdir -p lib/hello
echo 'package hello
import (
"fmt"
)
func Hello() {
fmt.Println("Hello!")
}
' > lib/hello/hello.go
echo 'package main
import (
"lib/hello"
)
func main() {
hello.Hello()
}
' > main.go
As you can see, we simply refactor the hello function to a library package hello
and want to import it in our main. Running this program with go run
, however, will yield a somewhat cryptic error:
go run main.go
$ main.go:4:2: package lib/hello is not in std (/usr/local/go/src/lib/hello)
We may use the Golang module system however, to alias our hello
package and import it from the local system using the replace
directive.
mkdir hello-golang-local
cd hello-golang-local
echo 'module friedrichkurz.me/hello-golang
go 1.22.5
require (
"friedrichkurz.me/hello" v0.0.1
)
replace (
"friedrichkurz.me/hello" => ./lib/hello
)
' > go.mod
mkdir -p lib/hello
echo 'package hello
import (
"fmt"
)
func Hello() {
fmt.Println("Hello!")
}
' > lib/hello/hello.go
echo 'module friedrichkurz.me/hello' > lib/hello/go.mod
echo 'package main
import (
hello "friedrichkurz.me/hello"
)
func main() {
hello.Hello()
}
' > main.go
As shown above, the imported local directory must (in this case) be a Golang module named
friedrichkurz.me/hello
. This means that it must have a separatego.mod
containng the directivemodule "friedrichkurz.me/hello"
.
With this change, the local directory is imported correctly and we may run the program successfully:
go run main.go
$ Hello!
(thewebivore.com) Using replace in go mod to point to your local module