The go Command and Modules
Real Go projects are organised as modules: a folder of code with a go.mod file that names the project and records the Go version and any libraries it depends on. This lesson creates a module, splits a program across files, and tours the go subcommands you'll use every day — run, build, fmt, vet, get, mod tidy and install.
Creating a module
Make a folder for the project and run go mod init with a module path. The path is the module's name; if you plan to publish the code it's usually the repository address, such as github.com/yourname/hello:
mkdir hello && cd hello go mod init example.com/hello
go: creating new go.mod: module example.com/hello
The new go.mod file is short:
module example.com/hello go 1.27.1
The go line records the language version the module is written for. It turns on that version's features, and if someone with an older toolchain builds the module, the go command fetches a new enough one for them.
A program in several files
A package can be split across any number of .go files in the same folder. They all share one namespace, so a function declared in one file can be called from another without importing anything:
module example.com/hello go 1.27
package main import "strings" func greeting(name string) string { return "Hello, " + strings.ToUpper(name[:1]) + name[1:] + "!" }
package main import "fmt" func main() { fmt.Println(greeting("gopher")) fmt.Println(greeting("world")) }
Run the whole package with a dot, meaning "the package in this folder":
go run .
Hello, Gopher! Hello, World!
Running go run main.go here would fail, because it compiles only that one file and greeting lives in the other. Inside a module, get into the habit of using go run ..
Building and installing
go build # creates ./hello (hello.exe on Windows), named after the module go build -o app # choose the output name go install # builds and copies the program into ~/go/bin
After go install, you can run hello from any folder, provided ~/go/bin is on your PATH. The same command installs tools other people have published: go install example.com/some/tool@latest.
Formatting and checking code
go fmt (which runs gofmt) rewrites your files into the standard layout. Given this badly spaced file:
package main import "fmt" func main(){ fmt.Println( "tidy me" ) }
running go fmt prints the names of the files it changed and leaves this behind:
package main import "fmt" func main() { fmt.Println("tidy me") }
go vet goes further and looks for code that compiles but is probably wrong, such as a Printf whose placeholders don't match its arguments. Run both before every commit; editors usually run them on save.
Using a third-party package
Packages from outside the standard library are imported by their module path. This program uses golang.org/x/text, a set of text-processing packages maintained by the Go team:
package main import ( "fmt" "golang.org/x/text/cases" "golang.org/x/text/language" ) func main() { title := cases.Title(language.English) fmt.Println(title.String("the go programming language")) }
The first go run . fails and tells you what to do:
main.go:6:2: no required module provides package golang.org/x/text/cases; to add it: go get golang.org/x/text/cases main.go:7:2: no required module provides package golang.org/x/text/language; to add it: go get golang.org/x/text/language
go get downloads the module and records it in go.mod; then the program runs:
go get golang.org/x/text go run .
go: downloading golang.org/x/text v0.42.0 go: added golang.org/x/text v0.42.0 The Go Programming Language
The go.mod file now has a require line, and a second file, go.sum, holds cryptographic checksums of everything downloaded so that later builds get exactly the same code. Commit both files. Running go mod tidy keeps go.mod accurate: it adds requirements your code imports, removes ones it no longer uses, and drops the // indirect marker go get left here, since the code now imports the package directly:
module example.com/words go 1.27.1 require golang.org/x/text v0.42.0
Modules are downloaded once into a shared cache (inside ~/go/pkg/mod) and reused by every project. You can search for packages and read their documentation on pkg.go.dev.
Command reference
| Command | What it does |
|---|---|
go mod init path | Starts a new module in the current folder |
go run . | Compiles and runs the package in this folder |
go build | Compiles an executable into the current folder |
go install | Compiles and installs into ~/go/bin |
go fmt ./... | Formats every package in the module (./... means "this folder and everything below it") |
go vet ./... | Reports suspicious code |
go test ./... | Runs tests (lesson 65) |
go get module@version | Adds or upgrades a dependency; @none removes it |
go mod tidy | Makes go.mod and go.sum match the imports |
go doc strings.Split | Shows documentation |
go fix ./... | Updates code to newer idioms and APIs automatically (lesson 68) |
main.go file unless it says otherwise. The easiest way to run them is one scratch module: go mod init example.com/scratch once, then replace main.go and use go run . each time.