Getter & Setter Methods
Part of the Object Oriented Programming section of Coddy's GO journey — lesson 49 of 107.
Since unexported fields can't be accessed directly from outside a package, you need to provide methods that allow controlled access. These are commonly called getters and setters.
In Go, the convention for getters is simple: use the field name with an uppercase first letter. Don't prefix with "Get"—just use Balance(), not GetBalance():
type BankAccount struct {
balance int // unexported
}
// Getter - returns the value
func (b *BankAccount) Balance() int {
return b.balance
}
// Setter - modifies the value with validation
func (b *BankAccount) SetBalance(amount int) {
if amount >= 0 {
b.balance = amount
}
}
The real power of setters is adding validation or business logic. Instead of letting external code set any value directly, you control what's allowed:
func (b *BankAccount) Deposit(amount int) bool {
if amount <= 0 {
return false
}
b.balance += amount
return true
}
This Deposit method acts as a specialized setter that enforces rules—no negative deposits allowed. External code must go through your methods, ensuring the struct always remains in a valid state. This is encapsulation in action: hiding the data while exposing controlled behavior.
Challenge
EasyLet's build a temperature converter that demonstrates proper encapsulation using getter and setter methods. You'll create a struct that stores temperature internally in Celsius but provides controlled access through methods with validation.
You'll organize your code across two files:
temperature.go: Create aTemperaturestruct with an unexportedcelsiusfield (float64). Implement the following methods:Celsius()- a getter that returns the current temperature in CelsiusSetCelsius(value float64)- a setter that only accepts values at or above absolute zero (-273.15). If the value is below this threshold, the temperature should remain unchanged.Fahrenheit()- returns the temperature converted to Fahrenheit using the formula:(celsius * 9/5) + 32SetFahrenheit(value float64)- converts the input from Fahrenheit to Celsius and stores it, but only if the resulting Celsius value is at or above -273.15
NewTemperature(celsius float64) *Temperaturethat creates a temperature initialized to the given value (assume valid input for the constructor).main.go: Read temperature values from input and demonstrate the getter/setter methods. Create a temperature, display its values in both units, then attempt to set new values and show the results.
The following inputs will be provided:
- Line 1: Initial Celsius value
- Line 2: New Celsius value to set
- Line 3: New Fahrenheit value to set
Format all temperature outputs with two decimal places. Print the following sequence:
- After creation:
C: [celsius] F: [fahrenheit] - After setting Celsius:
C: [celsius] F: [fahrenheit] - After setting Fahrenheit:
C: [celsius] F: [fahrenheit]
For example, given 25, -300, and 212, your output should be:
C: 25.00 F: 77.00
C: 25.00 F: 77.00
C: 100.00 F: 212.00Notice that the second line shows unchanged values because -300 is below absolute zero, so the setter rejected it. The third line shows the temperature after successfully setting 212°F (which converts to 100°C). This is the power of setters—they enforce rules that keep your data valid.
Cheat sheet
Unexported fields require getter and setter methods for controlled access from outside the package.
Getter Convention
In Go, getters use the field name with an uppercase first letter. Don't prefix with "Get":
type BankAccount struct {
balance int // unexported
}
// Getter - returns the value
func (b *BankAccount) Balance() int {
return b.balance
}Setter with Validation
Setters modify values and can include validation or business logic:
// Setter - modifies the value with validation
func (b *BankAccount) SetBalance(amount int) {
if amount >= 0 {
b.balance = amount
}
}Specialized Setters
Create methods that enforce specific rules instead of allowing direct value assignment:
func (b *BankAccount) Deposit(amount int) bool {
if amount <= 0 {
return false
}
b.balance += amount
return true
}This approach ensures encapsulation: hiding data while exposing controlled behavior, keeping structs in a valid state.
Try it yourself
package main
import (
"fmt"
)
func main() {
// Read input values
var initialCelsius float64
var newCelsius float64
var newFahrenheit float64
fmt.Scanln(&initialCelsius)
fmt.Scanln(&newCelsius)
fmt.Scanln(&newFahrenheit)
// TODO: Create a new Temperature using the constructor
// TODO: Print initial values in format "C: [celsius] F: [fahrenheit]" with 2 decimal places
// TODO: Attempt to set new Celsius value and print the result
// TODO: Attempt to set new Fahrenheit value and print the result
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of Go OOP
External FilesGo Workspace & ModulesPackages & ImportsExported vs Unexported NamesIntroduction to OOP in GoStructs as ClassesDefining Methods on StructsPointer vs Value ReceiversStruct InitializationConstructor FunctionsRecap - Simple Calculator4Interfaces
Introduction to InterfacesImplicit ImplementationInterface as ContractEmpty Interface (any)Type AssertionType SwitchInterface CompositionStringer & Error InterfacesRecap - Shape Calculator7Encapsulation
Exported vs Unexported FieldsPackage-Level EncapsulationGetter & Setter MethodsInformation Hiding in GoRecap - Student Records10Generics (Go 1.18+)
Introduction to GenericsType ParametersType ConstraintsGeneric StructsGeneric Methods WorkaroundRecap - Generic Collection2Types & Structs Deep Dive
Basic & Composite TypesCustom Type DefinitionsStruct TagsAnonymous StructsNested StructsZero Values & DefaultsRecap - Contact Book5Composition Over Inheritance
Why Go Has No InheritanceStruct Embedding BasicsMethod PromotionEmbedding Multiple StructsEmbedding vs AggregationShadowing Embedded MethodsRecap - Employee Hierarchy8Error Handling & OOP
The error InterfaceCustom Error TypesError Wrapping (fmt.Errorf)Sentinel Errorserrors.Is() and errors.As()Panic, Defer, and RecoverRecap - File Parser3Pointers & Memory
Pointer Basics in GoPointers to StructsPass by Value vs ReferenceThe new() FunctionGarbage Collection in GoRecap - Linked List Builder6Polymorphism in Go
Polymorphism via InterfacesDuck Typing in GoInterface Satisfaction RulesPolymorphic CollectionsDependency InjectionRecap - Payment Processor9Concurrency & OOP
Goroutines BasicsChannels & CommunicationBuffered vs Unbuffered ChanSelect Statementsync.Mutex & sync.RWMutexsync.WaitGroupThread-Safe Struct DesignRecap - Worker Pool