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 possui pelo menos zero métodos, todo tipo satisfaz automaticamente a interface vazia. Isso a torna capaz de conter 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 apelido para interface{}. Eles são completamente intercambiáveis, mas any é mais limpo 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á um tradeoff. Quando um valor é armazenado em uma interface vazia, você perde o acesso às informações de seu tipo específico.
Você não pode chamar métodos ou acessar campos diretamente sem antes extrair o tipo subjacente. As próximas lições cobrirão como recuperar o tipo concreto de uma interface vazia usando type assertions e type switches.
Desafio
FácilVamos construir um contêiner de armazenamento flexível que pode conter valores de qualquer tipo usando a interface vazia. Você criará uma caixa simples que demonstra como o any permite armazenar diferentes tipos na mesma estrutura.
Você organizará seu código em dois arquivos:
box.go: Defina uma structBoxcom um único campoContentdo tipoany. Crie uma função construtoraNewBoxque aceite um valor de qualquer tipo e retorne um ponteiro para um Box contendo esse valor. Adicione um métodoDescribeque retorne uma string mostrando o que está armazenado na caixa.main.go: Leia diferentes valores da entrada, crie caixas contendo um inteiro, uma string e um booleano, e então 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 lição aqui é que sua única struct Box pode armazenar um inteiro, uma string ou um booleano—tudo porque o tipo any aceita valores de qualquer tipo. Cada caixa contém algo diferente, mas todas são do mesmo tipo Box.
Folha de consulta
A interface vazia (interface{}) é uma interface com zero métodos. Como todo tipo em Go possui pelo menos zero métodos, todo tipo satisfaz automaticamente a interface vazia, tornando-a capaz de conter 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 apelido para interface{}. Elas são completamente intercambiáveis, mas any é mais limpo de ler:
var value any = "Go is awesome"A interface vazia é útil para lidar com valores de tipos desconhecidos ou variados. Funções podem aceitar argumentos de qualquer tipo:
func PrintAnything(v any) {
fmt.Println("Value:", v)
}
func main() {
PrintAnything(100)
PrintAnything("text")
PrintAnything(3.14)
}Compromisso (Tradeoff): Quando um valor é armazenado em uma interface vazia, você perde o acesso às informações de seu tipo específico. Você não pode chamar métodos ou acessar campos diretamente sem primeiro extrair o tipo subjacente usando asserções de tipo (type assertions) ou switches de tipo (type switches).
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: Criar caixas para cada valor usando NewBox
// TODO: Imprimir a descrição de cada caixa usando o método Describe
// Use as variáveis para evitar erros de compilação (remova estas linhas ao implementar)
_ = intVal
_ = strVal
_ = boolVal
// Exemplo de formato de saída:
// 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 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