Every Go file starts with a package declaration, and all files in the same directory must share the same package name — that’s Go’s unit of code organization. A module is one level up: a collection of packages versioned and distributed together, declared by a go.mod file. Visibility has no dedicated keyword; an identifier (function, type, variable, struct field) starting with an uppercase letter is exported and visible to other packages, while lowercase is unexported and private to its own package.
Capitalization is the visibility system
There's no public, private, or protected keyword in Go. Instead, the compiler enforces a simple rule based on the first letter of an identifier's name.
package mathutil
func Add(a, b int) int { // exported: capital A, usable by other packages
return helper(a, b)
}
func helper(a, b int) int { // unexported: lowercase, private to mathutil
return a + b
}A package importing mathutil can call mathutil.Add, but has no way to reference helper at all — it's simply not visible outside the package.
Importing packages
The import block lists packages by their module path. The standard library uses short paths ("fmt", "net/http"); third-party packages use their full repository path ("github.com/user/repo"), fetched and recorded in go.mod/go.sum by go get.
import (
"fmt" // standard library
"net/http" // standard library
"github.com/gin-gonic/gin" // third-party, from go.mod
)The internal/ directory convention
Go recognizes one special directory name: any package under a path containing internal/ can only be imported by code inside the same parent tree. This gives a module a way to share code across its own packages without exposing it as part of the module's public API — a middle ground between fully exported and single-package-private.