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.
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