Issue with modules

Hi,
I have a problem with modules. It doesn’t work for me.
It looks like that:

❯ tree
.
├── go.mod
├── main.go
└── mymodule
    └── mypackage.go
❯ cat go.mod
module mymodule

go 1.19
❯ cat mymodule/mypackage.go
package main

import "fmt"

func main() {
	fmt.Println("Hello, Modules!")
}

func PrintHello() {
	fmt.Println("Hello, Modules! This is mypackage speaking!")
}
❯ cat main.go
package main

import (
	"fmt"

	"mymodule/mypackage"
)

func main() {
	fmt.Println("Hello, Modules!")

	mypackage.PrintHello()
}

After running main.go I am getting error:

❯ go run main.go
main.go:6:2: package mymodule/mypackage is not in GOROOT (/opt/homebrew/Cellar/go/1.19.5/libexec/src/mymodule/mypackage)

Do you know what I am making wrong?

Hi, Daniel, welcome to the forum!

Your mymodule/mypackage.go file should start with package mypackage instead of package main. Generally, package main is for all of the files that live in the same folder as your main.go. There are exceptions, but you only use them when you know that you need to use them.

mymodule/mypackage.go also does not need a main function. That function is only used in your main package (usually in main.go) as the single entry point to your program.

When you run your package, use go run ..

go run main.go only compiles main.go, so the go command complains that it cannot find mymodule/mypackage. When you run go run ., the entire directory is inspected (including go.mod), so the compiler knows that mymodule/mypackage is inside of the mypackage directory.

1 Like

Thank you so much for welcome and so good explanation.
Unfortunately I still have the problem. I fixed issues what you pointed out.
Now it looks like that:

❯ tree
.
├── go.mod
├── main.go
└── mymodule
    └── mypackage.go

2 directories, 3 files
❯ cat go.mod
module mymodule

go 1.19
❯ cat main.go
package main

import (
	"fmt"

	"mymodule/mypackage"
)

func main() {
	fmt.Println("Hello, Modules!")

	mypackage.PrintHello()
}
❯ cat mymodule/mypackage.go
package mypackage

import "fmt"

func PrintHello() {
	fmt.Println("Hello, Modules! This is mypackage speaking!")
}
❯ ls
go.mod   main.go  mymodule
❯ go run .
main.go:6:2: package mymodule/mypackage is not in GOROOT (/opt/homebrew/Cellar/go/1.19.5/libexec/src/mymodule/mypackage)

Maybe something with varaibles?

❯ go env
GO111MODULE="auto"
GOARCH="arm64"
GOBIN=""
GOCACHE="/Users/XXX/Library/Caches/go-build"
GOENV="/Users/XXX/Library/Application Support/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="arm64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/XXX/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/XXX/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/opt/homebrew/Cellar/go/1.19.5/libexec"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/opt/homebrew/Cellar/go/1.19.5/libexec/pkg/tool/darwin_arm64"
GOVCS=""
GOVERSION="go1.19.5"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/Users/XXX/test/go/go.mod"
GOWORK=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/dv/j8hz28sj4tb__4l4ngdt_4fr0000gn/T/go-build247017480=/tmp/go-build -gno-record-gcc-switches -fno-common"

Your own modules need to have a “domain” that hosts them.

Usually it’s GitHub or GitLab. Though for your local experiments you can even use example.com, eg. example.com/mymodule.

Also make sure that your import actually states where to find the package, but it will be available under the declared package name in the importing scope!

So if you use the module name from my example, you would import as example.com/mymodule/mymodule and then use mypackage.PrintHello()!

1 Like

Thank you. It works.

❯ tree
.
├── go.mod
├── main.go
└── mymodule
    └── mypackage.go

2 directories, 3 files
❯ cat go.mod
module example.com/mymodule

go 1.19
❯ cat main.go
package main

import (
	"fmt"
	"example.com/mymodule/mymodule"
)

func main() {
	fmt.Println("Hello, Modules!")

	mypackage.PrintHello()
}
❯ cat mymodule/mypackage.go
package mypackage

import "fmt"

func PrintHello() {
	fmt.Println("Hello, Modules! This is mypackage speaking!")
}