Packages

As a project grows, placing every source file in one directory becomes difficult to maintain.

Instead of:

main.go
helper.go
crypto.go
json.go
storage.go
parser.go
network.go
...

Go organizes code into packages.

Each package has a single responsibility and groups related source files together.


Project Structure

Example:

myproject/

├── go.mod
├── main.go

└── calculator/
    └── calculator.go

The directory calculator represents a package.


Defining a Package

calculator/calculator.go

package calculator
 
func Add(a, b int) int {
    return a + b
}

Every source file begins with a package declaration.


Importing a Package

main.go

package main
 
import (
    "fmt"
    "myproject/calculator"
)
 
func main() {
    fmt.Println(calculator.Add(2, 3))
}

Output:

5

Import Paths

The import path is:

Module Name
+
Directory Name

Example:

go.mod

module myproject

Directory:

calculator/

Import:

import "myproject/calculator"

The import path is not simply the package name.


Package Names

Usually the directory name and package name are identical.

calculator/

contains

package calculator

Although Go allows different names, matching them is the standard convention.


Packages as Namespaces

Every exported identifier belongs to its package.

Examples:

fmt.Println()
 
os.Args
 
json.Marshal()
 
calculator.Add()

General pattern:

Package.Identifier

This applies to:

  • Functions

  • Types

  • Variables

  • Constants

  • Interfaces


Exported Types

Suppose:

package calculator
 
type Book struct {
    Title string
}

In another package:

var book calculator.Book

The package name qualifies the type.

This is similar to namespaces in C++:

calculator::Book

Exported vs Unexported Identifiers

Go uses capitalization to determine visibility.

Exported:

func Add()
 
type Book struct {
    Title string
}

Accessible from other packages.

Unexported:

func subtract()
 
type Book struct {
    pages int
}

Accessible only inside the same package.

No public or private keywords are needed.


Accessing Struct Fields

Given:

type Book struct {
    Title string
    pages int
}

This works:

book.Title

This does not:

book.pages

Because pages begins with a lowercase letter.

The same export rule applies to:

  • Functions

  • Methods

  • Types

  • Variables

  • Constants

  • Struct fields


Multiple Files in a Package

Example:

calculator/
 
add.go
subtract.go
multiply.go

Each file begins with:

package calculator

Go combines all files in the package during compilation.


Package Aliases

Long package names can be shortened.

import calc "myproject/calculator"

Usage:

calc.Add(2, 3)

Standard Library Packages

Frequently used packages include:

fmt

Console output.

os

Operating system interaction.

encoding/json

JSON encoding and decoding.

crypto/aes

AES encryption.

crypto/rand

Cryptographically secure random numbers.


Common Beginner Mistakes

Wrong Import Path

Incorrect:

import "calculator"

Correct:

import "myproject/calculator"

The module name is part of the import path.


Forgetting Capitalization

func add()

Cannot be accessed outside the package.

Use:

func Add()

when the function is intended to be public.


Using Package Name Inside the Same Package

Inside package calculator:

Incorrect:

calculator.Add()

Correct:

Add()

Code inside a package refers to its own identifiers directly.


Confusing Package Name with Import Path

Import path:

myproject/calculator

Package name:

calculator

These are related but not identical concepts.


Comparison with C++

GoC++
PackageNamespace
calculator.Add()calculator::Add()
calculator.Bookcalculator::Book
Uppercase = exportedpublic
Lowercase = package-privateprivate (roughly equivalent)

Packages provide organization and namespacing without introducing additional complexity.


Session Summary

Topics covered:

  • Packages

  • Import paths

  • Package names

  • Namespaces

  • Exported identifiers

  • Struct field visibility

  • Multiple files within a package

  • Package aliases

Practical skills gained:

  • Organizing code into packages

  • Importing custom packages

  • Understanding Go’s visibility rules

  • Recognizing packages as namespaces


Key Takeaways

  • Packages organize related code.

  • Every exported identifier is accessed as Package.Identifier.

  • Import paths are based on the module name and directory structure.

  • Uppercase identifiers are exported.

  • Lowercase identifiers are visible only within the same package.

  • A package may consist of multiple source files.


Next Topics