Recebedores de Ponteiro vs Valor
Parte da seção Programação Orientada a Objetos do Journey de GO da Coddy — lição 8 de 107.
Métodos podem ter um receptor de valor ou um receptor de ponteiro. Um receptor de valor trabalha em uma cópia da struct. Um receptor de ponteiro trabalha na struct original e pode modificar seus campos.
Receptor de valor — funciona em uma cópia
type Counter struct {
Count int
}
func (c Counter) GetCount() int {
return c.Count
}
// Isso NÃO modifica o original
func (c Counter) IncrementWrong() {
c.Count++ // Altera apenas a cópia!
}Receiver de ponteiro — modifica o original
// Isso MODIFICA o original
func (c *Counter) Increment() {
c.Count++
}
func (c *Counter) Reset() {
c.Count = 0
}Usando ambos juntos
func main() {
counter := Counter{Count: 0}
counter.Increment()
counter.Increment()
fmt.Println(counter.GetCount()) // Saída: 2
counter.Reset()
fmt.Println(counter.GetCount()) // Saída: 0
}Use um receptor de valor quando o método apenas lê dados. Use um receptor de ponteiro (*StructName) quando o método precisa modificar os campos da struct. O Go lida automaticamente com a referência — você chama ambos da mesma forma.
Desafio
MédioAdicione métodos à struct Wallet usando os tipos de receptor corretos:
GetBalance— receptor de valor, retorna o saldo atualDeposit— receptor de ponteiro, adiciona o valor ao saldoWithdraw— receptor de ponteiro, subtrai o valor apenas se houver fundos suficientes
Experimente você mesmo
package main
import "fmt"
func main() {
var balance, deposit, withdraw float64
fmt.Scan(&balance, &deposit, &withdraw)
w := Wallet{Balance: balance}
fmt.Printf("Balance: %.2f\n", w.GetBalance())
w.Deposit(deposit)
fmt.Printf("After deposit: %.2f\n", w.GetBalance())
w.Withdraw(withdraw)
fmt.Printf("After withdrawal: %.2f\n", w.GetBalance())
fmt.Printf("Final balance: %.2f\n", w.GetBalance())
}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