Packages and imports
Back to the recipe. A pie recipe does not explain how to make butter or flour: you take them ready-made. And at the top of the recipe there is a list of what you will need. A Go program works in a similar way.
A program often needs ready-made code: to print text or to turn letters into uppercase. In Go, such code lives in packages, and a program brings in only the ones it needs:
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println(strings.ToUpper("hello")) // HELLO
}Let's take apart the line inside main step by step:
- The call
strings.ToUpperconsists of the package name, a dot and the function name. - It takes
"hello"and returns the same text in capital letters. - That result goes straight into
fmt.Println, and the program printsHELLO.
The import block
The import block at the top of the file is the recipe's shopping list. Each import brings in one package. You can write imports in one of two forms.
Here the shopping-list picture is off in one way. An extra item on a shopping list does no harm, but an extra import, as you saw in the lesson on compile errors, stops the build.
One package
The line import "fmt" has two parts:
importis the keyword "I'm bringing in a package";"fmt"is the path to the package, in double quotes.
You write this form when the program needs one package: for example, when it only prints text with fmt.
A group of packages
Several imports are combined into a group. After the word import you open a parenthesis, write the paths one per line and close the parenthesis—as in the example above.
You can also write two separate imports in a row, import "fmt" and import "strings", and the program builds too. But a group is shorter and reads as one list, so it is what people usually write.
Package path and name
An import gives the path to a package, while code refers to the package by its name. Here is how they relate:
- the path goes in quotes:
"fmt","strings","math/rand"; - the package's name in code usually matches the last part of its path: for
"math/rand"it isrand; - standard library packages are installed together with Go, so you import them without downloading anything.
A package is a directory
A package is all the .go files in one directory (folder) that are compiled together. Three rules follow from that:
- each file of a package starts with a
packageline with the same name; - a function declared in one file of a package is visible in its other files without an import;
- a package's name usually matches its directory's name, while a program with
package maincan live in a directory with any name.
Program and library
By the name in the package line, packages come in two kinds.
The package main
The package named main is special: together with the function main, it makes an executable program, and its execution starts in main. This is the package that go run and go build build.
The function main is required. Without it, the build stops with the error function main is undeclared in the main package.
A library
A package with any other name is a library. It does not run on its own: its functions are called by other packages that import it.
fmt and strings are libraries of exactly this kind. The command go run answers a library file with an error: there is nothing in it to run.
The interview answer
Interviewers like to ask this: "What is a package, and what do package main and import do?" The answer combines three facts from this lesson:
- a package is the files of one directory;
package mainwith the functionmainis the program's entry point;importbrings in another package by its path, and an unused import is a compile error.
Exported names
Outside a package, only names that start with an uppercase letter are visible—the exported names. That is why Println and ToUpper start with a capital letter.
A name that starts with a lowercase letter stays inside its package, and an import does not open it. The rule covers all names, not only functions: the value math.Pi is visible outside because it starts with a capital P.
fmt.Println(strings.ToLower("GO"), strings.Repeat("ab", 3)) // go abababThis line has three calls:
strings.ToLower("GO")returnsgoin lowercase.strings.Repeat("ab", 3)repeatsabthree times.fmt.Printlnprints both results separated by a space.
Common mistake
The name of a function from a package is written in lowercase:
package main
import "fmt"
func main() {
fmt.println("hello") // ✗
}undefined: fmt.println (but have Println)The package fmt has no exported name println, so the compiler does not find it. In parentheses, it suggests the name that does exist—Println.
Key points
- A package is all the
.gofiles in one directory that are compiled together. package maintogether with the functionmainmakes an executable program, while a package with any other name is a library.- An import brings in a package by its path in quotes, and code refers to it by name:
strings.ToUpper. - Outside a package, only names that start with a capital letter are visible.
Subscribe to take the course
The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.