Packages & Modules Basics
10 examples to get you started with Packages & Modules - 7 basic and 3 intermediate.
Search across all documentation pages
10 examples to get you started with Packages & Modules - 7 basic and 3 intermediate.
mkdir moddemo && cd moddemo.go mod init example.com/moddemo.go run . after saving them as main.go (or the path shown).go mod init writes go.mod with your module path.
// Run in shell first:
// go mod init example.com/moddemoexample.com/... for learning).go.mod is the versioned root for every package under this directory tree.go.mod unless you split modules.Related: Packages and Modules: Go's Unit of Distribution - packages vs modules mental model
Split code across packages under the same module.
// greet/greet.go
package greet
import "fmt"
func Hello(name string) string {
return fmt.Sprintf("hello, %s", name)
}// main.go
package main
import (
"fmt"
"example.com/moddemo/greet"
)
func main() {
fmt.Println(greet.Hello("Go"))
}module path + /directory.go run .Related: Package Naming & internal/ Directories - naming and visibility rules
go get records a semver requirement in go.mod.
go get github.com/google/uuid@latestpackage main
import (
"fmt"
"github.com/google/uuid"
)
func main() {
fmt.Println(uuid.NewString())
}go get updates go.mod and go.sum.@v1.6.0 instead of @latest.Related: go.mod, go.sum & Minimal Version Selection - how versions resolve
Remove unused requirements and add missing ones.
go mod tidygo mod tidy would change files - use go mod tidy -diff or commit hooks.go.sum aligned with actual imports.Related: Packages, Modules & Project Layout Best Practices - hygiene habits
Inspect what the toolchain selected.
go list -m all
go list -m -versions github.com/google/uuidall prints the build list for the current module.-versions queries available tags from the origin (network required).Related: Pseudo-Versions, replace & retract Directives - overrides and bad releases
internal/ blocks imports from outside the parent tree.
moddemo/
go.mod
cmd/app/main.go
internal/config/config.go
// internal/config/config.go
package config
const Port = 8080// cmd/app/main.go
package main
import (
"fmt"
"example.com/moddemo/internal/config"
)
func main() {
fmt.Println(config.Port)
}example.com/moddemo cannot import internal/config.internal/ over comments for "do not use" APIs.Related: Standard Project Layout for Services and Libraries - cmd and internal layout
Import for init only, not direct symbol use.
package main
import (
"fmt"
_ "example.com/moddemo/register" // triggers init in register package
)
func main() {
fmt.Println("drivers registered")
}// register/register.go
package register
func init() {
// register plugin, driver, or http handler
}init functions in dependency order._ "github.com/lib/pq") and image formats.Related: Import Cycles, Blank Imports & Dot Imports - when side-effect imports fit
Point a requirement at a local path during development.
// go.mod snippet
module example.com/moddemo
go 1.26
require example.com/lib v0.0.0
replace example.com/lib => ../libreplace is for development; avoid committing machine-specific paths to shared main branches without documentation.replace paths on your laptop unless you commit them.go.work for multi-module repos when several modules edit each other daily.Related: go work: Workspace Mode for Multi-Module Repos - workspace without replace hacks
Develop multiple modules together without editing each go.mod.
# From repo root with sibling modules app/ and lib/
go work init ./app ./lib
go work use ./app ./lib// app/go.mod
module example.com/app
go 1.26
require example.com/lib v0.0.0go.work applies only on your machine; do not publish it as the library contract.GOWORK=off forces module-only mode for reproducible CI comparisons.use lines as new modules join the monorepo.Related: go work: Workspace Mode for Multi-Module Repos - full workspace workflow
Thin main, logic in packages, private code in internal/.
myapp/
go.mod
cmd/myapp/main.go
internal/server/server.go
pkg/client/client.go // optional: stable public API for other repos
// cmd/myapp/main.go
package main
import "example.com/myapp/internal/server"
func main() {
server.Run()
}cmd/ holds one directory per binary; each is package main.internal/ is enforced private; pkg/ is conventional public API (still your choice to support).cmd/.Related: Standard Project Layout for Services and Libraries - full layout guidance
Stack versions: This page was written for Go 1.26.x (Green Tea GC default, go fix modernizers - verify patch at build), chi (latest - verify at build), gin (latest - verify at build), echo (latest - verify at build), google.golang.org/grpc (latest - verify at build), sigs.k8s.io/controller-runtime (latest - verify at build), kubebuilder (latest - verify at build), tinygo (latest - verify board targets at build), wazero (latest - verify at build), and golangci-lint (latest - verify linter set at build).
Reviewed by Chris St. John·Last updated Jul 19, 2026