# Packages and Modules

> Source: https://learn-go.org/packages-and-modules/
> Part of Learn Go, free to read.

Every Go file starts by declaring its package:

```go
package main
```

A package is a directory. Every `.go` file in that directory must declare the same package name, and together they form one unit — files in the same package can use each other's identifiers with no import.

`package main` is special: it produces an executable, and needs a `func main()`.

## Exported means capitalised

Go's only access control is the case of the first letter:

```go
package pricing

const TaxRate = 0.2          // exported — usable as pricing.TaxRate
const baseMargin = 0.15      // unexported — package-private

func Total(items []Item) int { }    // exported
func applyMargin(n int) int { }     // unexported

type Item struct {
    SKU      string          // exported field
    costCents int            // unexported field
}
```

That is the whole mechanism. No `public`, no `private`. It applies to constants, variables, functions, types, methods and struct fields alike.

The consequence worth knowing early: **an unexported field is invisible to `encoding/json`**, so a struct field you forgot to capitalise silently disappears from your API responses.

## Modules

A module is a collection of packages versioned together, defined by `go.mod` at its root:

```bash
go mod init github.com/you/myapp
```

```go go.mod
module github.com/you/myapp

go 1.23

require (
    github.com/google/uuid v1.6.0
    golang.org/x/sync v0.8.0
)
```

The module path is the import prefix for everything inside it. A package in `internal/pricing/` is imported as `github.com/you/myapp/internal/pricing`.

```bash
go get github.com/google/uuid    # add a dependency
go mod tidy                      # add what is used, remove what is not
go mod why github.com/x/y        # why is this in my graph?
```

`go.sum` records a cryptographic hash of every module version, verified on every build. Commit both files.

## Imports

```go
import (
    "fmt"                                  // standard library
    "net/http"

    "github.com/google/uuid"               // third party

    "github.com/you/myapp/internal/pricing" // your own
)
```

`gofmt` groups and sorts these. Two forms worth knowing:

```go
import mrand "math/rand"       // alias, to disambiguate
import _ "github.com/lib/pq"   // blank — for side effects only (driver registration)
```

An unused import is a **compile error**, not a warning. That is a small thing that keeps generated Go tidy in a way other languages are not.

## The internal directory

A package under a directory named `internal` can only be imported by code within the same module subtree:

```text
github.com/you/myapp/
  internal/pricing/     <- importable only inside myapp
  pkg/client/           <- importable by anyone
```

This is enforced by the compiler and is the right default: **put everything in `internal/` unless you intend other projects to import it.** Once something is publicly importable you own its API.

## A standard layout

```text
myapp/
  go.mod
  go.sum
  cmd/
    server/main.go        # one directory per binary
    worker/main.go
  internal/
    pricing/             # domain logic
      pricing.go
      pricing_test.go
    storage/             # database access
    httpapi/             # handlers
  pkg/                   # only if genuinely reusable by others
```

`cmd/` holds thin `main` packages that wire things together; the real code lives in `internal/`. For a small tool, a single `main.go` at the root is perfectly fine — do not build this structure before you need it.

## init and package state

```go
var registry = make(map[string]Handler)

func init() {
    registry["default"] = defaultHandler
}
```

`init()` runs once, after package-level variables are initialised, before `main`. A package can have several, and they run in file order.

Use it rarely. Initialisation order across packages is hard to reason about, `init` cannot return an error, and it makes testing awkward. An explicit constructor called from `main` is almost always better.

## Naming

Go's naming conventions are unusually strong, and following them makes code look native:

- **Package names are short, lowercase, single words**: `http`, `pricing`, `strconv`. No underscores, no camelCase, no plurals.
- **Do not stutter.** In package `pricing`, name the function `Total`, not `PricingTotal` — callers write `pricing.Total`.
- **Short names for short scopes.** `i`, `r`, `w`, `err` are idiomatic. Long descriptive names are for package-level identifiers.
- **Interfaces that hold one method** end in `-er`: `Reader`, `Writer`, `Stringer`.

## Exercise

```go
// Sketch the layout for a URL-shortener module `github.com/you/shortly`:
//   - a binary at cmd/shortly
//   - domain logic (creating and resolving short codes) that other repos must NOT import
//   - a storage package, also private
//   - one exported type and one unexported helper in the domain package
// Write the go.mod, and the package + import lines for each file.
```

## Common questions

### `internal/` or `pkg/`?

`internal/` by default. It is compiler-enforced privacy, and it means you can refactor freely because nothing outside your module can depend on it. Move something to `pkg/` only when you have decided to support it as a public API.

### Why is an unused import an error rather than a warning?

Deliberate strictness — it keeps builds clean and stops dead imports accumulating. It is occasionally annoying while debugging, which is what the blank identifier `_` is for as a temporary measure.

### Should I use `init()`?

Rarely. It cannot return an error, its ordering across packages is subtle, and it makes tests harder to isolate. Prefer an explicit `New...` constructor called from `main`, where failures can be handled.
