A Função new()
Parte da seção Programação Orientada a Objetos do Journey de GO da Coddy. Lição 22 de 107.
Go fornece uma função integrada chamada new() que aloca memória para um tipo e retorna um ponteiro para ele. A memória alocada é inicializada com o valor zero do tipo.
p := new(int) // aloca memória para um int
fmt.Println(*p) // 0 (valor zero)
fmt.Println(p) // 0xc000018030 (endereço de memória)A função new() recebe um tipo como argumento e retorna um ponteiro para um valor zero recém-alocado desse tipo. Isso é particularmente útil quando você precisa de um ponteiro, mas não tem uma variável existente para referenciar.
Com structs, new() cria um ponteiro para uma struct com todos os campos definidos como seus valores zero.
type Person struct {
Name string
Age int
}
p := new(Person)
fmt.Println(p.Name) // "" (string vazia)
fmt.Println(p.Age) // 0Você pode se perguntar quando usar new() em vez do operador de endereço &. As duas abordagens abaixo são equivalentes:
// Usando new()
p1 := new(Person)
// Usando operador de endereço com literal
p2 := &Person{}A sintaxe &Person{} é mais comum na prática porque permite inicializar os campos ao mesmo tempo. Use new() quando você quiser especificamente uma instância com valor zero e preferir semântica explícita de alocação de memória.
Desafio
FácilVamos criar um gerenciador de configuração que demonstra como new() aloca memória e inicializa structs com seus valores zero. Você verá como essa abordagem difere do uso do operador de endereço com um literal de struct.
Você organizará seu código em dois arquivos:
config.go: Defina uma structServerConfigcom os camposHost(string),Port(int),MaxConnections(int) eDebugMode(bool). Crie duas funções:NewServerConfig, que usanew()para alocar umaServerConfige retorna diretamente o ponteiro (com todos os valores zero)ConfigureServer, que recebe um ponteiro*ServerConfigjunto com uma string de host e um inteiro de porta, e então define esses campos na configuração por meio do ponteiro
Displayem*ServerConfigque retorne uma string formatada mostrando todos os valores da configuração.main.go: Leia um host e uma porta da entrada. Primeiro, crie uma configuração usandoNewServerConfig()e exiba-a para mostrar os valores zero. Em seguida, useConfigureServerpara definir o host e a porta, e exiba a configuração novamente para mostrar os valores atualizados.
As seguintes entradas serão fornecidas:
- Linha 1: Nome do host (string)
- Linha 2: Número da porta (inteiro)
Seu método Display deve retornar uma string exatamente neste formato:
Host: [Host]
Port: [Port]
MaxConnections: [MaxConnections]
DebugMode: [DebugMode]Imprima a saída de exibição duas vezes, uma antes da configuração (mostrando os valores zero) e outra depois da configuração (mostrando o host e a porta atualizados).
Por exemplo, dadas as entradas localhost e 8080, sua saída deverá ser:
Host:
Port: 0
MaxConnections: 0
DebugMode: false
Host: localhost
Port: 8080
MaxConnections: 0
DebugMode: falseObserve como a primeira exibição mostra todos os valores zero (string vazia, 0, 0, false), porque new() inicializa tudo com valores zero. Depois de chamar ConfigureServer, somente o host e a porta mudam, enquanto os outros campos permanecem com seus valores zero.
Experimente você mesmo
package main
import (
"fmt"
)
func main() {
// Ler entrada
var host string
var port int
fmt.Scanln(&host)
fmt.Scanln(&port)
// TODO: Crie uma config usando NewServerConfig() e exiba-a
// Isso mostrará os valores zero
// TODO: Use ConfigureServer para definir o host e a porta
// TODO: Exiba a config novamente para mostrar os valores atualizados
}
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 ExternosWorkspace e Módulos do GoPacotes e ImportsNomes Exportados vs. Não ExportadosIntrodução à OOP em GoStructs como ClassesDefinindo Métodos em StructsReceptores de Ponteiro vs. de ValorInicialização de StructsFunções ConstrutorasRecapitulação — Calculadora Simples4Interfaces
Introdução às InterfacesImplementação ImplícitaInterface como ContratoInterface Vazia (any)Asserção de TipoSwitch de TipoComposição de InterfacesInterfaces Stringer e ErrorRecapitulação - Calculadora de Formas7Encapsulamento
Campos Exportados vs. Não ExportadosEncapsulamento no Nível de PacoteMétodos Getters e SettersOcultação de Informações em GoRecapitulação - Registros de Alunos10Genéricos (Go 1.18+)
Introdução aos genéricosParâmetros de tipoRestrições de tipoStructs genéricasAlternativa para métodos genéricosRecapitulação - Coleção genérica13Padrões de Projeto — Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão Abstract FactoryPadrão ObserverPadrão Strategy2Tipos e Structs em Profundidade
Tipos Básicos e CompostosDefinições de Tipos PersonalizadosTags de StructStructs AnônimasStructs AninhadasValores Zero e PadrõesRecapitulação - Livro de Contatos5Composição em vez de herança
Por que Go não tem herançaNoções básicas de incorporação de structsPromoção de métodosIncorporação de várias structsIncorporação vs agregaçãoOcultação de métodos incorporadosRecapitulação - Hierarquia de funcionários8Tratamento de Erros e OOP
A interface errorTipos de Erro PersonalizadosEncapsulamento de Erros (fmt.Errorf)Erros Sentinelaerrors.Is() e errors.As()Panic, Defer e RecoverRecapitulação - Analisador de Arquivos3Ponteiros e Memória
Fundamentos de Ponteiros em GoPonteiros para StructsPassagem por Valor vs. ReferênciaA Função new()Coleta de Lixo em GoRecapitulação - Construtor de Lista Ligada6Polimorfismo em Go
Polimorfismo via InterfacesDuck Typing em GoRegras de Satisfação de InterfacesColeções PolimórficasInjeção de DependênciasRecapitulação - Processador de Pagamentos9Concorrência e OOP
Fundamentos de GoroutinesCanais e comunicaçãoCanais com e sem bufferInstrução selectsync.Mutex e sync.RWMutexsync.WaitGroupDesign de structs thread-safeRevisão - Worker PoolPratique por conta própria: Compilador de Go online