Métodos Getter y Setter
Parte de la sección Programación Orientada a Objetos del Journey de GO de Coddy. Lección 49 de 107.
Como no se puede acceder directamente a los campos no exportados desde fuera de un paquete, debes proporcionar métodos que permitan un acceso controlado. Estos suelen llamarse getters y setters.
En Go, la convención para los getters es sencilla: usa el nombre del campo con la primera letra en mayúscula. No lo prefijes con "Get"; simplemente usa Balance(), no GetBalance():
type BankAccount struct {
balance int // no exportado
}
// Getter - devuelve el valor
func (b *BankAccount) Balance() int {
return b.balance
}
// Setter - modifica el valor con validación
func (b *BankAccount) SetBalance(amount int) {
if amount >= 0 {
b.balance = amount
}
}
El verdadero poder de los setters consiste en añadir validación o lógica de negocio. En lugar de permitir que el código externo establezca cualquier valor directamente, controlas qué está permitido:
func (b *BankAccount) Deposit(amount int) bool {
if amount <= 0 {
return false
}
b.balance += amount
return true
}
Este método Deposit actúa como un setter especializado que impone reglas: no se permiten depósitos negativos. El código externo debe pasar por tus métodos, lo que garantiza que la estructura siempre permanezca en un estado válido. Esto es la encapsulación en acción: ocultar los datos mientras se expone un comportamiento controlado.
Desafío
FácilConstruyamos un convertidor de temperatura que demuestre una encapsulación adecuada mediante métodos getter y setter. Crearás una estructura que almacena internamente la temperatura en Celsius, pero proporciona acceso controlado mediante métodos con validación.
Organizarás tu código en dos archivos:
temperature.go: Crea una estructuraTemperaturecon un campocelsiusno exportado (float64). Implementa los siguientes métodos:Celsius()- un getter que devuelve la temperatura actual en CelsiusSetCelsius(value float64)- un setter que solo acepta valores iguales o superiores al cero absoluto (-273.15). Si el valor está por debajo de este umbral, la temperatura debe permanecer sin cambios.Fahrenheit()- devuelve la temperatura convertida a Fahrenheit usando la fórmula:(celsius * 9/5) + 32SetFahrenheit(value float64)- convierte la entrada de Fahrenheit a Celsius y la almacena, pero solo si el valor Celsius resultante es igual o superior a -273.15
NewTemperature(celsius float64) *Temperatureque cree una temperatura inicializada con el valor indicado (supón que la entrada del constructor es válida).main.go: Lee valores de temperatura de la entrada y demuestra los métodos getter/setter. Crea una temperatura, muestra sus valores en ambas unidades, después intenta establecer nuevos valores y muestra los resultados.
Se proporcionarán las siguientes entradas:
- Línea 1: Valor inicial en Celsius
- Línea 2: Nuevo valor en Celsius que se establecerá
- Línea 3: Nuevo valor en Fahrenheit que se establecerá
Formatea todas las salidas de temperatura con dos decimales. Imprime la siguiente secuencia:
- Después de la creación:
C: [celsius] F: [fahrenheit] - Después de establecer Celsius:
C: [celsius] F: [fahrenheit] - Después de establecer Fahrenheit:
C: [celsius] F: [fahrenheit]
Por ejemplo, dadas las entradas 25, -300 y 212, tu salida debería ser:
C: 25.00 F: 77.00
C: 25.00 F: 77.00
C: 100.00 F: 212.00Observa que la segunda línea muestra valores sin cambios porque -300 está por debajo del cero absoluto, por lo que el setter lo rechazó. La tercera línea muestra la temperatura después de establecer correctamente 212°F (que se convierte en 100°C). Este es el poder de los setters. Hacen cumplir reglas que mantienen tus datos válidos.
Pruébalo tú mismo
package main
import (
"fmt"
)
func main() {
// Lee los valores de entrada
var initialCelsius float64
var newCelsius float64
var newFahrenheit float64
fmt.Scanln(&initialCelsius)
fmt.Scanln(&newCelsius)
fmt.Scanln(&newFahrenheit)
// TODO: Crea un nuevo Temperature usando el constructor
// TODO: Imprime los valores iniciales en el formato "C: [celsius] F: [fahrenheit]" con 2 decimales
// TODO: Intenta establecer el nuevo valor de Celsius e imprime el resultado
// TODO: Intenta establecer el nuevo valor de Fahrenheit e imprime el resultado
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de POO en Go
Archivos externosEspacio de trabajo y módulos de GoPaquetes e importacionesNombres exportados vs. no exportadosIntroducción a la POO en GoStructs como clasesDefinición de métodos en structsReceptores de puntero vs. de valorInicialización de structsFunciones constructorasResumen - Calculadora simple4Interfaces
Introducción a las interfacesImplementación implícitaLa interfaz como contratoInterfaz vacía (any)Type AssertionType SwitchComposición de interfacesInterfaces Stringer y ErrorResumen: Calculadora de figuras7Encapsulamiento
Campos exportados vs. no exportadosEncapsulamiento a nivel de paqueteMétodos Getter y SetterOcultamiento de información en GoResumen - Registros de estudiantes10Genéricos (Go 1.18+)
Introducción a los GenéricosParámetros de tipoRestricciones de tipoStructs genéricosSolución alternativa para métodos genéricosResumen - Colección genérica13Patrones de diseño - Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón Abstract FactoryPatrón ObserverPatrón Strategy2Inmersión profunda en Tipos y Structs
Tipos básicos y compuestosDefiniciones de tipos personalizadosEtiquetas de StructsStructs anónimosStructs anidadosValores cero y por defectoRepaso - Libreta de contactos5Composición sobre herencia
Por qué Go no tiene herenciaConceptos básicos de incrustación de structsPromoción de métodosIncrustación de múltiples structsIncrustación vs AgregaciónShadowing de métodos incrustadosResumen - Jerarquía de empleados8Manejo de Errores y OOP
La interfaz errorTipos de errores personalizadosEnvoltura de errores (fmt.Errorf)Errores centinelaerrors.Is() y errors.As()Panic, Defer y RecoverResumen - Analizador de archivos3Punteros y Memoria
Fundamentos de punteros en GoPunteros a StructsPaso por valor vs referenciaLa función new()Garbage Collection en GoResumen - Constructor de Linked List6Polimorfismo en Go
Polimorfismo mediante interfacesDuck Typing en GoReglas de satisfacción de interfacesColecciones polimórficasInyección de dependenciasResumen - Procesador de pagos9Concurrencia y POO
Fundamentos de GoroutinesChannels y comunicaciónChannels con buffer vs. sin bufferSentencia Selectsync.Mutex y sync.RWMutexsync.WaitGroupDiseño de estructuras Thread-SafeResumen - Worker PoolPractica por tu cuenta: Compilador de Go online