← Back to Go Course | Chapter 10: Packages & Modules | Lesson 6 of 6

Exported vs Unexported Identifiers

Capitalizing a name in Go is like putting a PUBLIC sign on it -- anything starting lowercase quietly stays PRIVATE to its own package.

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

markup
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)
}

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

markup
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)
}

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

markup
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())
}
Common Mistakes
  1. Trying to access a lowercase (unexported) identifier from another package and being confused by the compile error.
  2. Capitalizing every single identifier by default 'to be safe', exposing internal details that should stay private implementation.
  3. 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.
Chapter Summary
  • 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:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.