How to import a package and call into it, what a package name has to do with its path, and what a capital letter decides about who can see a name.
1 Import a package and call a function
This is the smallest complete Go program that uses a package. import names what you want, and from then on you reach into it with a dot.
package main
import "fmt"
func main() {
fmt.Println("Hello from Go.")
}$ go run main.go
Hello from Go.2 Import more than one package
Parentheses after import hold as many as you like, one per line. This is the form you will write almost every time.
Import something and never use it and the program will not compile. Go treats an unused import as a mistake to fix, not a warning to ignore.
import (
"fmt"
"strings"
)
func main() {
fmt.Println(strings.ToUpper("shout")) // SHOUT
}3 Use the package name, not the path
"math/rand" is a path with two parts, but the package it declares is called rand, so that is what you type.
They usually match the last segment. Usually, not always, which matters in a moment.
import "math/rand"
rand.Intn(6) + 1 // a dice roll4 Alias a package when two share a name
"crypto/rand" and "math/rand" both declare rand. Put a name in front of one import and that becomes what you type instead.
import (
"math/rand"
crand "crypto/rand"
)
rand.Intn(6) // the maths one
crand.Read(b) // the cryptographic one5 Name things without repeating the package
The package name is already sitting in front of everything inside it, so repeating it reads badly. It is bytes.Buffer, not bytes.BytesBuffer.
That prefix is why package names stay short, lowercase, and free of underscores.
var buf bytes.Buffer // good
var b bytes.BytesBuffer // what you avoidWriting your own
6 Declare package main for a runnable program
Every file opens with a package clause. Declaring main tells go build to produce something you can execute, and func main is where it starts. Any other name builds a package for other code to import.
package main // an executable
package greet // a library, imported by something else7 Create a module and a package
go mod init writes the file. The path you give it is what other people will import, so it is normally the repository URL.
One directory is one package. Every file in it opens with the same package clause, and the folder name is what shows up in the import path.
mkdir hello
cd hello
go mod init example.com/hellohello/
├── go.mod // module example.com/hello
├── main.go // package main
├── greet/
│ └── greet.go // package greet
└── internal/
└── secret/
└── secret.go8 Export a name with a capital letter
That is the whole visibility system. No public or private keyword, and it works the same on functions, types, struct fields, constants, and variables.
Reaching for an unexported name from outside is a compile error, not a warning.
// Package greet builds greeting lines.
package greet
// Formal is exported. Anyone importing greet can call it.
func Formal(name string) string {
return fmt.Sprintf("Good evening, %s.", name)
}
// casual is unexported. Only files in package greet can call it.
func casual(name string) string {
return "hey " + name
}greet.Formal("Keith") // fine
greet.casual("Keith") // name casual not exported by package greet9 Import your own package
Standard library packages use their short path. Yours use the module path from go.mod with the directory on the end.
Keep the standard library in its own group above the rest, separated by a blank line. gofmt sorts each group for you.
import (
"fmt"
"example.com/hello/greet"
)
fmt.Println(greet.Formal("Keith"))10 Keep a package private with internal
Anything under it is private to the module that holds it, and the compiler enforces that. It is where implementation details go when you publish a library and do not want them becoming part of your public API.
// From inside example.com/hello: fine.
import "example.com/hello/internal/secret"
// From any other module: use of internal package not allowed11 Import for side effects, or into scope
An underscore imports a package only for its side effects, which is how database drivers and image decoders register themselves. A dot drops every name into your file's scope, and outside test helpers it makes code hard to follow.
import (
_ "image/png" // registers the PNG decoder, nothing else
. "math" // Sqrt(2) instead of math.Sqrt(2)
)Putting it together
One module, three packages, and a capital letter deciding what the outside world can reach.
// main.go
package main
import (
"fmt"
"example.com/hello/greet"
"example.com/hello/internal/secret"
)
func main() {
fmt.Println(greet.Formal("Keith"))
fmt.Println(greet.Casual("Keith"))
fmt.Println(secret.Key)
}$ go run .
Good evening, Keith.
hey Keith
reachable only inside example.com/hello
$ go list ./...
example.com/hello
example.com/hello/greet
example.com/hello/internal/secretImport a name, call it with a dot. Everything else is where that name lives and whether you are allowed to see it.