Interface fmt.Stringer
Parte da seção Programação Orientada a Objetos do Journey de GO da Coddy — lição 75 de 107.
A interface fmt.Stringer controla como seus tipos aparecem quando impressos. É uma das interfaces mais comumente implementadas em Go, definida no pacote fmt:
type Stringer interface {
String() string
}Quando você passa um valor para fmt.Println, fmt.Printf com %v, ou funções semelhantes, o Go verifica se o tipo implementa Stringer. Se implementar, o Go chama o método String() para obter a representação em texto.
type Temperature struct {
Celsius float64
}
func (t Temperature) String() string {
return fmt.Sprintf("%.1f°C", t.Celsius)
}
func main() {
temp := Temperature{Celsius: 23.5}
fmt.Println(temp) // 23.5°C
}Sem o método String(), a impressão mostraria o formato padrão da struct: {23.5}. Ao implementar o Stringer, você controla exatamente como seu tipo se apresenta.
Isso é particularmente útil para tipos onde os valores brutos dos campos não transmitem o significado de forma clara. Um tipo Duration pode ser exibido como "2h 30m" em vez de mostrar nanossegundos brutos, ou um tipo User pode mostrar um nome formatado em vez de todos os seus campos.
Desafio
FácilVamos construir um sistema de rastreamento de tempo que exibe durações em um formato amigável para humanos! Você implementará a interface fmt.Stringer para controlar como seus tipos personalizados aparecem quando impressos.
Você organizará seu código em dois arquivos:
duration.go: Defina seus tipos relacionados ao tempo com representações de string personalizadas.Crie uma struct
Durationque armazena um número total de minutos como um inteiro. Implemente o métodoString()para que, quando impresso, ele seja exibido em um formato legível como2h 30mpara 150 minutos, ou0h 45mpara 45 minutos. Horas e minutos devem sempre ser mostrados.Crie uma struct
Taskcom campos paraName(string) eTime(Duration). ImplementeString()em Task para exibir no formato[Name]: [duration], onde a duração usa seu próprio método String.main.go: Construa e exiba tarefas com suas durações.Leia uma contagem de tarefas, então, para cada tarefa, leia seu nome e duração em minutos. Crie instâncias de Task e imprima cada uma diretamente usando
fmt.Println—a interface Stringer cuidará da formatação automaticamente.Após imprimir todas as tarefas, calcule e imprima o tempo total de todas as tarefas no formato:
Total: [duration]
As seguintes entradas serão fornecidas:
- Linha 1: Número de tarefas
- Linhas seguintes: Nome da tarefa e minutos (duas linhas por tarefa)
Por exemplo, dado:
3
Code Review
90
Meeting
45
Documentation
120Sua saída deve ser:
Code Review: 1h 30m
Meeting: 0h 45m
Documentation: 2h 0m
Total: 4h 15mE dado:
2
Design
180
Testing
65Sua saída deve ser:
Design: 3h 0m
Testing: 1h 5m
Total: 4h 5mAo implementar Stringer, seus tipos se integram perfeitamente às funções de impressão do Go. Em vez de ver campos brutos da struct como {90}, você obtém uma saída significativa que faz sentido para os usuários.
Folha de consulta
A interface fmt.Stringer controla como os tipos aparecem quando são impressos:
type Stringer interface {
String() string
}Quando você passa um valor para fmt.Println ou fmt.Printf com %v, o Go verifica se o tipo implementa Stringer. Se implementar, o Go chama o método String() para obter a representação em texto.
Exemplo de implementação:
type Temperature struct {
Celsius float64
}
func (t Temperature) String() string {
return fmt.Sprintf("%.1f°C", t.Celsius)
}
func main() {
temp := Temperature{Celsius: 23.5}
fmt.Println(temp) // 23.5°C
}Sem o método String(), a impressão mostra o formato padrão da struct: {23.5}. Ao implementar Stringer, você controla exatamente como seu tipo se apresenta, tornando a saída mais significativa e amigável para o usuário.
Experimente você mesmo
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Ler o número de tarefas
line, _ := reader.ReadString('\n')
numTasks, _ := strconv.Atoi(strings.TrimSpace(line))
// TODO: Criar um slice para armazenar as tarefas
// TODO: Rastrear o total de minutos
for i := 0; i < numTasks; i++ {
// Ler o nome da tarefa
name, _ := reader.ReadString('\n')
name = strings.TrimSpace(name)
// Ler a duração da tarefa em minutos
minutesLine, _ := reader.ReadString('\n')
minutes, _ := strconv.Atoi(strings.TrimSpace(minutesLine))
// TODO: Criar uma Task com o name e Duration
// TODO: Imprimir a tarefa (fmt.Println usará a interface Stringer)
// TODO: Adicionar os minutos ao total
_ = name
_ = minutes
}
// TODO: Imprimir a duração total no formato "Total: Xh Ym"
}
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 Parser11Biblioteca Padrão & POO
io.Reader & io.Writersort.InterfaceInterface fmt.Stringerencoding/json com StructsInterface http.HandlerRecapitulação - Modelos de API REST3Ponteiros 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