Packages and Modules
fmt mathGo code is organized in packages, and packages in modules. A package is a directory of .go files that share a package clause. A module is a tree of packages with a go.mod file at its root, which names the module path and lists its dependencies. This repository is the module github.com/clivern/tuck.
package mainA package is imported by its full path: the module path plus the directory. The geometry package lives in the geometry/ folder next to this file. An alias, geo, is the name used in this file. A blank import runs init and gives no name to call.
import (
"fmt"
geo "github.com/clivern/tuck/90_packages_and_modules/geometry"
_ "github.com/clivern/tuck/90_packages_and_modules/notice"
)
func main() {Exported names are used through the name chosen at the import, here geo.
c := geo.Circle{Radius: 2}
fmt.Println(c.Area(), c.Diameter())Package-level variables are initialized, and init functions run, before main. Steps lists them: geometry's own inits, in source order, then the package that was blank-imported.
fmt.Println(geo.Default)
fmt.Println("init:", geo.Steps)Lower-case names are private to their package.
// geometry.round(1.234)
// error: name round not exported by package geometryThird-party packages are added with go get, which records them in go.mod and go.sum, for example: go get golang.org/x/sync/errgroup. go mod tidy removes dependencies you no longer use.
fmt.Println("see the geometry folder for the package source")
}$ go run ./90_packages_and_modules 12.57 4.0cm {1} init: [geometry geometry again notice] see the geometry folder for the package source $ go list ./90_packages_and_modules/... github.com/clivern/tuck/90_packages_and_modules github.com/clivern/tuck/90_packages_and_modules/geometry github.com/clivern/tuck/90_packages_and_modules/geometry/internal/units github.com/clivern/tuck/90_packages_and_modules/notice $ head -3 go.mod module github.com/clivern/tuck go 1.27.1
90_packages_and_modules/geometry/geometry.go
Package geometry is a tiny library used by the Packages and Modules example. The package name is the last element of its import path.
package geometry
import (
"math"
"github.com/clivern/tuck/90_packages_and_modules/geometry/internal/units"
)Names starting with an upper case letter are exported: other packages can use them.
type Circle struct {
Radius float64
}Area is exported, so callers can use it.
func (c Circle) Area() float64 {
return round(math.Pi * c.Radius * c.Radius)
}Diameter returns the diameter formatted in centimeters.
func (c Circle) Diameter() string {
return units.Centimeters(2 * c.Radius)
}round is lower case, so it is private to this package.
func round(f float64) float64 {
return math.Round(f*100) / 100
}Default is set by init.
var Default CircleSteps names each init function as it runs. Inits in one package run in source order, and a package finishes its inits before the package that imports it.
var Steps []string
func init() {
Default = Circle{Radius: 1}
Steps = append(Steps, "geometry")
}
func init() {
Steps = append(Steps, "geometry again")
}90_packages_and_modules/geometry/internal/units/units.go
Package units formats lengths. It lives under internal/, so only code inside the geometry directory tree can import it.
package units
import "fmt"Centimeters formats a length in centimeters.
func Centimeters(v float64) string {
return fmt.Sprintf("%.1fcm", v)
}90_packages_and_modules/notice/notice.go
Package notice has no API. The packages example blank-imports it so init runs for its side effect.
package notice
import "github.com/clivern/tuck/90_packages_and_modules/geometry"init runs because of that blank import. geometry is imported here, so its inits have already finished.
func init() {
geometry.Steps = append(geometry.Steps, "notice")
}