Modules & Packages (go mod)

Real Go programs span many files and pull in third-party libraries. This lesson covers how Go organizes code: packages (folders of related code) and modules (versioned collections managed by go mod ). By the end you'll structure a project, export names across packages, and add dependencies.

Learn Modules & Packages (go mod) in our free Go course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick recall.

Part of the free Go course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

What You'll Learn in This Lesson

One module contains one or more packages. The package you run lives in package main and has a func main() ; everything else is a library package imported by others.

1️⃣ Packages & Exported Names

Every Go file begins with package X , and all files in one folder must share that name. The rule for visibility is delightfully simple: a name starting with a capital letter is exported (visible to other packages); a lowercase name is private to its package. No public / private keywords — just capitalization.

Another package imports it by its import path (module path + folder) and calls only its exported names.

Your turn. Rename the function so it can be called from outside its package.

2️⃣ The go.mod File

A module is declared by a go.mod file at the project root. You create it once with go mod init <path> . It records the module's import path, the minimum Go version, and every dependency with its exact version — so anyone who clones your project gets the same builds.

3️⃣ The go Command Workflow

Day to day you'll use a handful of commands. go mod init starts a module, go get adds a dependency, go mod tidy syncs go.mod with what your code actually imports, and go run . builds and runs the current package.

4️⃣ Using a Third-Party Package

Once a dependency is in go.mod , importing and using it is no different from the standard library — Go fetches it from the source repository and caches it. Below we generate a UUID with a popular library after a single go get .

These are the steps to start a project and run it with a dependency. Put them in the correct order:

B, D, C, E, A. Initialize the module first (it must exist before anything else), add the dependency, write the code that uses it, run go mod tidy to reconcile go.mod , then run. In practice go get and writing code interleave, but init is always first and run last.

No. format is lowercase, so it's unexported — visible only inside package util . Rename it Format to call it from another package.

go mod init example.com/myapp — this writes a go.mod declaring the module path. Run it once at the project root.

It adds any imports your code uses but go.mod is missing, and removes dependencies no longer imported. It keeps go.mod / go.sum in sync with the actual code.

Q: What's the difference between a package and a module?

A package is a single folder of related code. A module is a versioned bundle of one or more packages with a go.mod file and an import path. You import packages; you version and distribute modules.

Purely by capitalization. A capitalized identifier (function, type, field, constant) is exported and visible to importers; a lowercase one is package-private. This applies to struct fields too — which is why JSON only sees capitalized fields.

Only the first time you fetch a dependency. Go caches downloaded modules locally, so subsequent builds work offline. go.sum verifies that cached copies haven't changed.

Run go get example.com/dep@latest (or a specific version like @v1.5.0 ), then go mod tidy . Go updates go.mod and go.sum to the chosen version.

No blanks — a design brief. Sketch the files and commands for a small two-package project, deciding which names must be exported. This mirrors how every real Go repository is laid out.

Practice quiz

What is a Go package?

  • A single file
  • A folder of files sharing one package name
  • A compiled binary
  • A remote server

Answer: A folder of files sharing one package name. A package is a directory of source files that all declare the same package name.

How is a name made exported (visible outside its package)?

  • A keyword 'export'
  • A capitalized first letter
  • An export tag
  • Being in main

Answer: A capitalized first letter. Capitalized identifiers are exported; lowercase ones are package-private.

What file declares a Go module?

  • package.json
  • go.mod
  • module.go
  • Gopkg.toml

Answer: go.mod. go.mod declares the module path and its dependencies.

Which command creates a new module?

  • go new
  • go mod init
  • go create
  • go module

Answer: go mod init. go mod init <path> creates the go.mod file for a new module.

Which command adds a dependency to your module?

  • go add
  • go install
  • go get
  • go fetch

Answer: go get. go get adds (or upgrades) a dependency and records it in go.mod.

Which command removes unused dependencies and adds missing ones?

  • go clean
  • go mod tidy
  • go fix
  • go vet

Answer: go mod tidy. go mod tidy reconciles go.mod/go.sum with the imports your code actually uses.

What is the purpose of go.sum?

  • Lists TODOs
  • Pins and verifies dependency checksums
  • Stores secrets
  • Configures the editor

Answer: Pins and verifies dependency checksums. go.sum records cryptographic checksums so builds are reproducible and verifiable.

How do you import one of your own packages?

  • By file path
  • By module path plus the package folder
  • By package name only
  • You cannot

Answer: By module path plus the package folder. Internal packages are imported using the module path joined with the subfolder.

Which package name marks an executable program?

  • package app
  • package main
  • package exe
  • package run

Answer: package main. package main (with func main) builds an executable; other names build libraries.

Can a lowercase function from another package be called directly?

  • Yes, always
  • No, it is unexported and package-private
  • Only in tests
  • Only with reflection

Answer: No, it is unexported and package-private. Lowercase names are unexported, so they are not accessible from outside their package.