Go Runtime module file structure

Is it possible to have all modules as submodules of main.go?
I want to create something like this:


  • main.go
  • go.mod
  • docker-compose.yml
  • Dockerfile
  • modules
    • module1.go
    • module2.go

I am trying to do this on Windows and when I try to build it into docker im getting this:

Hello @lkopacka,

A Go module is a collection of packages that live under the same root defined by the go.mod file. Typically a Go project will only contain a single module with all the necessary source files at the root.

Any subfolder within the root would contain its own package. A package should have the same name as its parent folder and contain only source files related to it. All defined functions, types, variables and constants are visible within the package (all its source files), but only the ones exported (capitalized) are accessible when using (importing) the package.

Typically you’d define packages with reusable interfaces for very specific domains (see how the Go standard lib’s modules are things like http, crypto, json and so on). This also makes it easier to test these individual packages.

So depending on what you mean with modules, you’d need split these into separate packages, or otherwise just have a single package with some logical split between source files. I’d advise you against trying to split things into too many packages, especially if you’re not exactly sure on what interfaces you’ll need to export yet.

Hope this helps.

Those are my project files, and I’m building them in Docker. But I’m getting:
main.go:6:2: package myproject/profile is not in GOROOT (/usr/local/go/src/myproject/profile)

I am trying to ask why this is happening when all the rules mentioned above seem in order?

    ├── main.go
    ├── go.mod
    ├── Dockerfile
    └── profile/
      └── profile.go


    package main

    import (


    func InitModule(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, initializer runtime.Initializer) error {
        if err := initializer.RegisterRpc("profile_update_metadata", profile.UpdateMetadata); err != nil {
            logger.Error("Unable to update profile's metadata, reason: %v", err)
            return err
        return nil;


    package profile

    import (

    func UpdateMetadata(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, payload string) (string, error) {
        return "{\"Success\":0}", nil

What’s the content of your go.mod file?


module myproject

go 1.21

require github.com/heroiclabs/nakama-common v1.28.1

require google.golang.org/protobuf v1.31.0 // indirect

I believe in profile.go you’re missing the import for “database/sql”.

Please try setting the go version to go 1.19 in the go.mod file and try again.

Yes, did miss “database/sql” when copying, but it is there.
And I did downgrade the go version in go.mod to 1.19
But the outcome is:

$ docker compose up --build
[+] Building 0.9s (12/14)
 => [internal] load build definition from Dockerfile                                                                                                                                                                         0.0s 
 => => transferring dockerfile: 32B                                                                                                                                                                                          0.0s 
 => [internal] load .dockerignore                                                                                                                                                                                            0.0s 
 => => transferring context: 2B                                                                                                                                                                                              0.0s 
 => [internal] load metadata for registry.heroiclabs.com/heroiclabs/nakama:3.18.0                                                                                                                                            0.4s 
 => [internal] load metadata for docker.io/heroiclabs/nakama-pluginbuilder:3.18.0                                                                                                                                            0.5s 
 => [go-builder 1/6] FROM docker.io/heroiclabs/nakama-pluginbuilder:3.18.0@sha256:c88a79f47824c3391e6ff2a09ae5f105b2dfbc367b5f162d0939daa4c00e0ecf                                                                           0.0s 
 => [stage-1 1/3] FROM registry.heroiclabs.com/heroiclabs/nakama:3.18.0@sha256:5091f870a6e4e2b3cfa1dd67c7f09fa913e601d2413fe6ae29da2e2f7d3e43ab                                                                              0.0s 
 => [internal] load build context                                                                                                                                                                                            0.0s 
 => => transferring context: 14.15kB                                                                                                                                                                                         0.0s 
 => CACHED [go-builder 2/6] WORKDIR /backend                                                                                                                                                                                 0.0s 
 => CACHED [go-builder 3/6] COPY go.mod .                                                                                                                                                                                    0.0s 
 => CACHED [go-builder 4/6] COPY *.go .                                                                                                                                                                                      0.0s 
 => CACHED [go-builder 5/6] COPY vendor/ vendor/                                                                                                                                                                             0.0s 
 => ERROR [go-builder 6/6] RUN go build --trimpath --mod=vendor --buildmode=plugin -o ./backend.so                                                                                                                           0.3s 
 > [go-builder 6/6] RUN go build --trimpath --mod=vendor --buildmode=plugin -o ./backend.so:
#0 0.303 main.go:6:2: package myproject/profile is not in std (/usr/local/go/src/myproject/profile)
failed to solve: executor failed running [/bin/sh -c go build --trimpath --mod=vendor --buildmode=plugin -o ./backend.so]: exit code: 1

I think you’re not copying the package directory into the docker container, add:

COPY profile/ profile/

to your Dockerfile

Yep, that’s it. Thanks a lot.