Every Go file starts with a package clause, and visibility rules depend entirely on package boundaries.
Every Go file begins with package name. All files in one directory form one package and share a namespace — a function defined in a.go is visible in b.go without importing anything.
The package named main is special: it builds into an executable, and its func main() (no arguments, no return value) is the entry point. Any other package name produces a library that other code imports.
Imports use the package's import path: standard library paths are short ("fmt", "net/http"), while your own packages are the module path plus the directory, e.g. "example.com/shop/internal/cart". You refer to the imported package by its name — the last path element by convention — so net/http is used as http.Get.
Visibility is decided by the first letter of an identifier:
Total,Cart,NewCartstart with an upper-case letter and are exported — visible to importers.total,cartare unexported — private to the package.
There are no public/private keywords; capitalisation is the whole rule, and it applies to functions, types, struct fields, methods and constants alike.
A directory named internal restricts importers: packages under a/b/internal/... can only be imported by code rooted at a/b. Use it to keep helpers out of your public API.
Each package may also have func init() functions that run automatically before main. They are handy for registration but make start-up order implicit, so keep them rare.
Example
// file: greet/greet.go
package greet
import "strings"
// Hello is exported (capital H); shout is not.
func Hello(name string) string { return "Hello, " + shout(name) }
func shout(s string) string { return strings.ToUpper(s) }
// file: main.go
// package main
//
// import (
// "fmt"
// "example.com/hello/greet"
// )
//
// func main() { fmt.Println(greet.Hello("gopher")) } // Hello, GOPHERRemember
- One directory = one package;
package main+func main()= a program - Upper-case first letter = exported, lower-case = package-private
internal/directories limit who may import a package
Watch out for
- Trying to call an unexported name like
greet.shoutfrom another package.