Dev Skills

Packages and visibility

A folder is a package, and capitalisation is your access control.

Topic 20 of 98 · 5 min to read · 45 min to build
After this topic you can
  • Write a module with two packages and call one from the other.
  • Explain how capitalisation decides what a package exports.
  • Fix an undefined error caused by a lowercase name.

Three things you need before writing anything real

A package is a folder of Go files compiled together. It is how you split a growing program into pieces, and it is the only privacy Go has: capitalised names are visible outside the package, lowercase names are not.

JSON is the text format most web APIs send and receive. Go turns a struct into JSON and back using the field tags you met with structs, so most JSON work in Go is describing your types accurately.

A test is code that runs your code and fails loudly when the answer is wrong. Testing is part of the Go toolchain, not a library you pick: a file ending _test.go, a function starting Test, and go test.

A folder is a package

Every .go file declares a package, and every file in one folder must declare the same one. Visibility is decided by capitalisation: a name starting with a capital letter is exported and visible outside the package; a lowercase name is private to it. There is no public or private keyword.

calc-demo/
go.modmodule example.com/calc-demo
main.gopackage main
calc/
calc.gopackage calc
calc_test.gopackage calc
a module with two packages
calc/calc.go
package calc
// Add is visible outside the package because it starts with a capital.
func Add(a, b int) int { return a + b }
// helper is private to this package.
func helper() {}
main.go
package main
import (
"fmt"
"example.com/calc-demo/calc" // module path + folder
)
func main() {
fmt.Println(calc.Add(2, 3))
}
This is one file of the two-package module above, so it only builds next to `calc/calc.go`; run it with `go run .` in the module folder. The package name is part of every call, so `calc.Add` reads well and `calc.CalcAdd` stutters. Do not repeat the package name in what it exports.
The short version
  • Every file in one folder declares the same package name.
  • Capitalised names are exported; lowercase ones are private to the package.
  • The import path is the module path plus the folder.
  • There is no public or private keyword, and none is needed.
  • Once a module has many packages, internal/ folders and import cycles come into play: see Packages in code in the tooling section.
Remember: Capitalisation is not style. It is the access modifier.
Build this before moving on
Split working code into two packages, make one function lowercase, and watch the import break.
Then try these in your own editor
  1. 1Create a calc package and call it from main.
  2. 2Use a blank import (_ "net/http/pprof") and work out what it is for.
  3. 3Alias an import and use the alias.
Check yourselfTake the Core language test