Exported vs Unexported Identifiers
Exported Identifiers
Any top-level function, type, variable, or constant whose name starts with an uppercase letter is exported, meaning code in other packages can access it after importing the package.
Example: Exported Identifiers
package main
import "fmt"
type Product struct {
Name string // exported field
}
func NewProduct(name string) Product {
return Product{Name: name}
}
func main() {
p := NewProduct("Widget")
fmt.Println(p.Name)
}
Login to try C/C++/Java/PHP code in the editor
Unexported Identifiers
A name starting with a lowercase letter is unexported, restricting it to the package it's declared in -- this is Go's entire mechanism for access control, with no private or public keywords needed.
Example: Unexported Identifiers
package main
import "fmt"
type product struct {
name string // unexported field, only usable within this package
}
func main() {
p := product{name: "Widget"}
fmt.Println(p.name)
}
Login to try C/C++/Java/PHP code in the editor
Exporting Struct Fields Selectively
A struct can mix exported and unexported fields, letting you expose only the parts meant for external use while keeping internal bookkeeping fields private to the package.
Note: Use unexported fields plus exported constructor/accessor functions to enforce invariants that direct field access would bypass.
Example: Exporting Struct Fields Selectively
package main
import "fmt"
type Account struct {
Owner string // exported
balance float64 // unexported: only this package can read/modify it directly
}
func NewAccount(owner string, initial float64) Account {
return Account{Owner: owner, balance: initial}
}
func (a Account) Balance() float64 {
return a.balance
}
func main() {
acc := NewAccount("Tara", 500)
fmt.Println(acc.Owner, acc.Balance())
}
Login to try C/C++/Java/PHP code in the editor
- Trying to access a lowercase (unexported) identifier from another package and being confused by the compile error.
- Capitalizing every single identifier by default 'to be safe', exposing internal details that should stay private implementation.
- Assuming exported/unexported applies within a package too -- it doesn't; all identifiers are visible to every file in the same package regardless of case.
- An identifier starting with an uppercase letter is exported -- visible to code in other packages.
- An identifier starting with a lowercase letter is unexported -- visible only within its own package.
- This capitalization rule applies to functions, types, variables, constants, and struct fields alike.
- Unexported identifiers are still fully visible to every file within the same package.
Chapter Quiz — Complete all 6 topics to unlock
0/6 topics done
Complete these topics first: