Fundamentos de Ponteiros em Go
Parte da seção Programação Orientada a Objetos do Journey de GO da Coddy — lição 19 de 107.
Um ponteiro é uma variável que armazena o endereço de memória de outra variável. Em vez de conter um valor diretamente, ele contém o local onde esse valor reside na memória. Ponteiros são fundamentais para Go e essenciais para a manipulação eficiente de dados.
Para criar um ponteiro, use o operador & para obter o endereço de uma variável e o operador * para declarar um tipo de ponteiro ou acessar o valor naquele endereço.
x := 42
p := &x // p contém o endereço de memória de x
fmt.Println(p) // 0xc000018030 (endereço de memória)
fmt.Println(*p) // 42 (valor naquele endereço)O operador & significa "endereço de" e retorna um ponteiro. O operador *, quando usado em um ponteiro, significa "valor em" e é chamado de desreferenciação. Você também pode modificar o valor original através do ponteiro.
x := 10
p := &x
*p = 25 // altera o valor através do ponteiro
fmt.Println(x) // 25 (variável original alterada)O tipo ponteiro é escrito como *T onde T é o tipo para o qual se aponta. Um ponteiro para um int tem o tipo *int.
var p *int // declara um ponteiro para int
x := 100
p = &x // p agora aponta para xO valor zero de um ponteiro é nil, o que significa que ele não aponta para nada. Tentar desreferenciar um ponteiro nil causa um pânico em tempo de execução (runtime panic), portanto, certifique-se sempre de que os ponteiros sejam inicializados antes do uso.
Desafio
FácilVamos construir um trocador de valores simples que demonstra o poder dos ponteiros para modificar variáveis por meio de seus endereços de memória.
Você organizará seu código em dois arquivos:
swap.go: Crie uma função chamadaSwapValuesque recebe dois ponteiros*intcomo parâmetros. Esta função deve trocar os valores para os quais esses ponteiros apontam—após chamá-la, cada variável deve conter o valor original da outra. A função não retorna nada; ela modifica os valores diretamente através dos ponteiros.main.go: Leia dois números inteiros da entrada, armazene-os em variáveis e, em seguida, use sua funçãoSwapValuespara trocar seus valores. Imprima ambos os valores antes e depois da troca para mostrar a mudança.
As seguintes entradas serão fornecidas:
- Linha 1: Primeiro número inteiro
- Linha 2: Segundo número inteiro
Formato de saída:
Before: a=[first] b=[second]
After: a=[first] b=[second]Por exemplo, dados 10 e 25, sua saída deve ser:
Before: a=10 b=25
After: a=25 b=10Lembre-se de usar o operador & ao passar suas variáveis para a função, e o operador * dentro da função para acessar e modificar os valores reais.
Folha de consulta
Um ponteiro é uma variável que armazena o endereço de memória de outra variável. Use o operador & para obter o endereço de uma variável, e o operador * para declarar um tipo de ponteiro ou acessar o valor naquele endereço.
x := 42
p := &x // p contém o endereço de memória de x
fmt.Println(p) // 0xc000018030 (endereço de memória)
fmt.Println(*p) // 42 (valor naquele endereço)O operador & significa "endereço de" e retorna um ponteiro. O operador *, quando usado em um ponteiro, significa "valor em" e é chamado de desreferenciação.
Você pode modificar o valor original através do ponteiro:
x := 10
p := &x
*p = 25 // altera o valor através do ponteiro
fmt.Println(x) // 25 (variável original alterada)O tipo do ponteiro é escrito como *T onde T é o tipo que está sendo apontado:
var p *int // declara um ponteiro para int
x := 100
p = &x // p agora aponta para xO valor zero de um ponteiro é nil. Tentar desreferenciar um ponteiro nil causa um pânico em tempo de execução (runtime panic).
Experimente você mesmo
package main
import "fmt"
func main() {
// Ler dois inteiros da entrada
var a, b int
fmt.Scanln(&a)
fmt.Scanln(&b)
// Imprimir valores antes da troca
fmt.Printf("Before: a=%d b=%d\n", a, b)
// TODO: Chamar a função SwapValues com ponteiros para a e b
// Lembre-se de usar o operador & para passar endereços
// Imprimir valores após a troca
fmt.Printf("After: a=%d b=%d\n", a, b)
}
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