Skip to content

Packages & Imports

Every Go source file begins with a package declaration. The package name groups related files together and controls what identifiers are visible to the outside world.

package main

The special package name main tells the Go toolchain that this package produces an executable binary. Every executable must have exactly one func main() inside package main — that is where execution begins.

package main
func main() {
// execution starts here
}

Any other package name (for example package mathutil) produces a library that other packages can import.

The import statement brings other packages into scope. You can import a single package or group multiple imports together in parentheses — Go style strongly prefers the grouped form whenever you need more than one:

// single import
import "fmt"
// grouped import — preferred
import (
"fmt"
"strings"
"strconv"
)

The import path is a string that identifies the package. Standard library packages use short paths like "fmt", "strings", "math/rand". Third-party packages use a full module path like "github.com/user/repo/pkg".

Occasionally you import a package solely for its side effects — typically to register a driver or handler during init(). In that case, use the blank identifier _ to suppress the “imported and not used” compile error:

import _ "database/sql/driver" // registers a driver; name not used directly

Go’s visibility rule is simple and enforced by the compiler: an identifier that starts with an uppercase letter is exported (visible to other packages); one that starts with a lowercase letter is unexported (package-private).

package mathutil
// Add is exported — other packages can call mathutil.Add
func Add(a, b int) int { return a + b }
// helper is unexported — invisible outside this package
func helper() {}

This applies to functions, types, variables, constants, struct fields, and interface methods alike.

Go ships with a rich standard library. A few packages you will use constantly:

PackagePurpose
fmtFormatted I/O: Println, Printf, Sprintf, Errorf
stringsString manipulation: Contains, Split, ToUpper, TrimSpace
strconvString ↔ number conversions: Itoa, Atoi, FormatFloat
errorsError creation: errors.New, errors.Is, errors.As
sortSorting slices and custom types
mathMath functions: math.Abs, math.Sqrt, math.Pi
timeTime values, durations, and formatting
package main
import (
"fmt"
"strconv"
"strings"
)
func main() {
// fmt: formatted output
fmt.Println("Go packages demo")
// strings: manipulating text
sentence := "the quick brown fox"
words := strings.Split(sentence, " ")
fmt.Println("Word count:", len(words))
fmt.Println("Uppercase:", strings.ToUpper(sentence))
fmt.Println("Contains 'fox':", strings.Contains(sentence, "fox"))
// strconv: converting between strings and numbers
n := 42
s := strconv.Itoa(n)
fmt.Println("int to string:", s)
parsed, err := strconv.Atoi("123")
if err == nil {
fmt.Println("string to int:", parsed)
}
// Combining packages together
parts := []string{"Go", strconv.Itoa(1), strconv.Itoa(22)}
fmt.Println("Joined:", strings.Join(parts, "."))
}
Which package name marks a Go file as producing an executable binary?
What does an identifier starting with a lowercase letter mean in Go?
When would you use a blank import `import _ "pkg"`?
Which of the following is the idiomatic Go style when importing multiple packages?