Métodos Getter e Setter
Parte da seção Programação Orientada a Objetos do Journey de GO da Coddy — lição 49 de 107.
Como campos não exportados não podem ser acessados diretamente de fora de um pacote, você precisa fornecer métodos que permitam o acesso controlado. Estes são comumente chamados de getters e setters.
Em Go, a convenção para getters é simples: use o nome do campo com a primeira letra maiúscula. Não use o prefixo "Get"—apenas use Balance(), não GetBalance():
type BankAccount struct {
balance int // não exportado
}
// Getter - retorna o valor
func (b *BankAccount) Balance() int {
return b.balance
}
// Setter - modifica o valor com validação
func (b *BankAccount) SetBalance(amount int) {
if amount >= 0 {
b.balance = amount
}
}
O verdadeiro poder dos setters é adicionar validação ou lógica de negócio. Em vez de permitir que o código externo defina qualquer valor diretamente, você controla o que é permitido:
func (b *BankAccount) Deposit(amount int) bool {
if amount <= 0 {
return false
}
b.balance += amount
return true
}
Este método Deposit atua como um setter especializado que impõe regras — depósitos negativos não são permitidos. O código externo deve passar pelos seus métodos, garantindo que a struct sempre permaneça em um estado válido. Isso é o encapsulamento em ação: escondendo os dados enquanto expõe um comportamento controlado.
Desafio
FácilVamos construir um conversor de temperatura que demonstra o encapsulamento adequado usando métodos getter e setter. Você criará uma struct que armazena a temperatura internamente em Celsius, mas fornece acesso controlado por meio de métodos com validação.
Você organizará seu código em dois arquivos:
temperature.go: Crie uma structTemperaturecom um campocelsiusnão exportado (float64). Implemente os seguintes métodos:Celsius()- um getter que retorna a temperatura atual em CelsiusSetCelsius(value float64)- um setter que aceita apenas valores iguais ou superiores ao zero absoluto (-273.15). Se o valor estiver abaixo desse limite, a temperatura deve permanecer inalterada.Fahrenheit()- retorna a temperatura convertida para Fahrenheit usando a fórmula:(celsius * 9/5) + 32SetFahrenheit(value float64)- converte a entrada de Fahrenheit para Celsius e a armazena, mas apenas se o valor Celsius resultante for igual ou superior a -273.15
NewTemperature(celsius float64) *Temperatureque cria uma temperatura inicializada com o valor fornecido (assuma uma entrada válida para o construtor).main.go: Leia os valores de temperatura da entrada e demonstre os métodos getter/setter. Crie uma temperatura, exiba seus valores em ambas as unidades, depois tente definir novos valores e mostre os resultados.
As seguintes entradas serão fornecidas:
- Linha 1: Valor Celsius inicial
- Linha 2: Novo valor Celsius para definir
- Linha 3: Novo valor Fahrenheit para definir
Formate todas as saídas de temperatura com duas casas decimais. Imprima a seguinte sequência:
- Após a criação:
C: [celsius] F: [fahrenheit] - Após definir Celsius:
C: [celsius] F: [fahrenheit] - Após definir Fahrenheit:
C: [celsius] F: [fahrenheit]
Por exemplo, dados 25, -300 e 212, sua saída deve ser:
C: 25.00 F: 77.00
C: 25.00 F: 77.00
C: 100.00 F: 212.00Observe que a segunda linha mostra valores inalterados porque -300 está abaixo do zero absoluto, então o setter o rejeitou. A terceira linha mostra a temperatura após definir com sucesso 212°F (que se converte em 100°C). Este é o poder dos setters — eles impõem regras que mantêm seus dados válidos.
Folha de consulta
Campos não exportados exigem métodos getter e setter para acesso controlado de fora do pacote.
Convenção de Getter
Em Go, os getters usam o nome do campo com a primeira letra maiúscula. Não use o prefixo "Get":
type BankAccount struct {
balance int // não exportado
}
// Getter - retorna o valor
func (b *BankAccount) Balance() int {
return b.balance
}Setter com Validação
Setters modificam valores e podem incluir validação ou lógica de negócio:
// Setter - modifica o valor com validação
func (b *BankAccount) SetBalance(amount int) {
if amount >= 0 {
b.balance = amount
}
}Setters Especializados
Crie métodos que imponham regras específicas em vez de permitir a atribuição direta de valores:
func (b *BankAccount) Deposit(amount int) bool {
if amount <= 0 {
return false
}
b.balance += amount
return true
}Essa abordagem garante o encapsulamento: ocultando dados enquanto expõe comportamento controlado, mantendo as structs em um estado válido.
Experimente você mesmo
package main
import (
"fmt"
)
func main() {
// Lê os valores de entrada
var initialCelsius float64
var newCelsius float64
var newFahrenheit float64
fmt.Scanln(&initialCelsius)
fmt.Scanln(&newCelsius)
fmt.Scanln(&newFahrenheit)
// TODO: Cria uma nova Temperature usando o construtor
// TODO: Imprime os valores iniciais no formato "C: [celsius] F: [fahrenheit]" com 2 casas decimais
// TODO: Tenta definir o novo valor de Celsius e imprime o resultado
// TODO: Tenta definir o novo valor de Fahrenheit e imprime o resultado
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos de OOP em Go
Arquivos ExternosGo Workspace e MódulosPacotes e ImportaçõesNomes Exportados vs Não ExportadosIntrodução a OOP em GoStructs como ClassesDefinindo Métodos em StructsRecebedores de Ponteiro vs ValorInicialização de StructsFunções ConstrutorasRecapitulação - Calculadora Simples4Interfaces
Introdução a InterfacesImplementação ImplícitaInterface como ContratoInterface Vazia (any)Type AssertionType SwitchComposição de InterfacesInterfaces Stringer & ErrorRecapitulação - Calculadora de Formas7Encapsulamento
Campos Exportados vs Não ExportadosEncapsulamento em Nível de PacoteMétodos Getter e SetterOcultação de Informação em GoRecapitulação - Registros de Estudantes10Generics (Go 1.18+)
Introdução a GenericsParâmetros de TipoRestrições de TipoStructs GenéricasSolução Alternativa para Métodos GenéricosRecapitulação - Coleção Genérica2Mergulho Profundo em Tipos e Structs
Tipos Básicos e CompostosDefinições de Tipos PersonalizadosStruct TagsStructs AnônimasStructs AninhadasZero Values e PadrõesRecapitulação - Agenda de Contatos5Composição em vez de Herança
Por que Go não possui HerançaFundamentos de Incorporação de StructsPromoção de MétodosIncorporando Múltiplas StructsIncorporação vs AgregaçãoShadowing de Métodos IncorporadosRecapitulação - Hierarquia de Funcionários8Tratamento de Erros e OOP
A Interface errorTipos de Erro PersonalizadosError Wrapping (fmt.Errorf)Erros Sentinelaerrors.Is() e errors.As()Panic, Defer e RecoverRecapitulação - File Parser3Ponteiros e Memória
Fundamentos de Ponteiros em GoPonteiros para StructsPassagem por Valor vs ReferênciaA Função new()Garbage Collection em GoRecapitulação - Construtor de Lista Encadeada6Polimorfismo em Go
Polimorfismo via InterfacesDuck Typing em GoRegras de Satisfação de InterfaceColeções PolimórficasInjeção de DependênciaRecapitulação - Processador de Pagamentos9Concorrência e OOP
Fundamentos de GoroutinesCanais e ComunicaçãoCanais com Buffer vs. Sem BufferInstrução Selectsync.Mutex e sync.RWMutexsync.WaitGroupDesign de Structs Thread-SafeRecapitulação - Worker Pool