Interface Vazia (any)
Parte da seção Programação Orientada a Objetos do Journey de GO da Coddy. Lição 28 de 107.
A interface vazia é uma interface com zero métodos. Como todo tipo em Go tem pelo menos zero métodos, todo tipo satisfaz automaticamente a interface vazia. Isso faz com que ela seja capaz de armazenar valores de qualquer tipo.
var anything interface{}
anything = 42
anything = "hello"
anything = true
anything = []int{1, 2, 3}A partir do Go 1.18, a palavra-chave any foi introduzida como um alias para interface{}. Elas são completamente intercambiáveis, mas any é mais fácil de ler.
var value any = "Go is awesome"A interface vazia é útil quando você precisa lidar com valores de tipos desconhecidos ou variados. Funções como fmt.Println a utilizam para aceitar argumentos de qualquer tipo:
func PrintAnything(v any) {
fmt.Println("Value:", v)
}
func main() {
PrintAnything(100)
PrintAnything("text")
PrintAnything(3.14)
}No entanto, há uma desvantagem. Quando um valor é armazenado em uma interface vazia, você perde o acesso às informações específicas sobre seu tipo.
Você não pode chamar métodos diretamente nem acessar campos sem antes extrair o tipo subjacente. As próximas lições abordarão como obter o tipo concreto de uma interface vazia usando asserções de tipo e switches de tipo.
Desafio
FácilVamos criar um contêiner de armazenamento flexível que possa conter valores de qualquer tipo usando a interface vazia. Você criará uma caixa simples que demonstra como any permite armazenar tipos diferentes na mesma estrutura.
Você organizará seu código em dois arquivos:
box.go: Defina uma estruturaBoxcom um único campoContentdo tipoany. Crie uma função construtoraNewBoxque aceite um valor de qualquer tipo e retorne um ponteiro para uma Box contendo esse valor. Adicione um métodoDescribeque retorne uma string mostrando o que está armazenado na caixa.main.go: Leia valores diferentes da entrada, crie caixas contendo um inteiro, uma string e um booleano e, em seguida, imprima a descrição de cada caixa para mostrar como o mesmo tipo Box pode conter valores completamente diferentes.
As seguintes entradas serão fornecidas:
- Linha 1: Um valor inteiro
- Linha 2: Um valor de string
- Linha 3: Um valor booleano (
trueoufalse)
Seu método Describe deve retornar uma string neste formato:
Box contains: [value]Por exemplo, dados 42, hello e true, sua saída deve ser:
Box contains: 42
Box contains: hello
Box contains: trueA principal ideia aqui é que sua única estrutura Box pode armazenar um inteiro, uma string ou um booleano: tudo isso porque o tipo any aceita valores de qualquer tipo. Cada caixa contém algo diferente, mas todas são do mesmo tipo Box.
Experimente você mesmo
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Ler valor inteiro
line1, _ := reader.ReadString('\n')
intVal, _ := strconv.Atoi(strings.TrimSpace(line1))
// Ler valor string
line2, _ := reader.ReadString('\n')
strVal := strings.TrimSpace(line2)
// Ler valor booleano
line3, _ := reader.ReadString('\n')
boolVal, _ := strconv.ParseBool(strings.TrimSpace(line3))
// TODO: Crie boxes para cada valor usando NewBox
// TODO: Imprima a descrição de cada box usando o método Describe
// Use as variáveis para evitar erros de compilação (remova estas linhas ao implementar)
_ = intVal
_ = strVal
_ = boolVal
// Formato de saída de exemplo:
// fmt.Println(box.Describe())
}
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