Encadeamento de Métodos
Parte da seção Programação Orientada a Objetos do Journey de GO da Coddy — lição 81 de 107.
Encadeamento de métodos (method chaining) é uma técnica onde os métodos retornam o receptor, permitindo que múltiplas chamadas de método sejam vinculadas em uma única instrução. Você já viu isso no padrão Builder, mas é um conceito independente útil em muitos contextos.
A chave é retornar um ponteiro para a struct de cada método:
type Query struct {
table string
columns []string
where string
limit int
}
func (q *Query) Select(cols ...string) *Query {
q.columns = cols
return q
}
func (q *Query) From(table string) *Query {
q.table = table
return q
}
func (q *Query) Where(condition string) *Query {
q.where = condition
return q
}
func (q *Query) Limit(n int) *Query {
q.limit = n
return q
}Agora você pode encadear estas chamadas fluentemente:
query := &Query{}
query.Select("name", "email").From("users").Where("active = true").Limit(10)Isso soa quase como linguagem natural em comparação com instruções separadas. O encadeamento de métodos funciona melhor quando as operações configuram ou modificam um objeto sem a necessidade de retornar outros valores. É comumente usado em construtores de consultas, APIs de configuração e bibliotecas de asserção de testes.
Lembre-se de que cada método deve usar um receptor de ponteiro e retornar *StructType para que o encadeamento funcione corretamente.
Desafio
FácilVamos construir um construtor de elementos HTML fluente que utiliza encadeamento de métodos para construir tags HTML com atributos e conteúdo! Esta é uma aplicação prática de encadeamento de métodos — você criará uma API que soa quase como linguagem natural ao construir elementos HTML.
Você organizará seu código em dois arquivos:
element.go: Defina seu construtor de elementos HTML com métodos encadeáveis.Crie uma struct
Elementque armazena o nome da tag, um mapa de atributos (string para string) e o conteúdo interno. Construa estes métodos encadeáveis que retornam*Element:NewElement(tag string)- construtor que cria um novo Element com o nome da tag fornecido e um mapa de atributos inicializado (vazio)Attr(key, value string)- adiciona um atributo ao elementoID(id string)- método de conveniência que define o atributo "id"Class(class string)- método de conveniência que define o atributo "class"Content(text string)- define o conteúdo interno do elemento
Adicione um método
Render()que retorna a string HTML. Os atributos devem aparecer em ordem alfabética pela chave. O formato é:<tag attr1="value1" attr2="value2">content</tag>Se não houver atributos, apenas renderize
<tag>content</tag>. Se não houver conteúdo, renderize<tag attr="value"></tag>.main.go: Construa elementos HTML usando encadeamento de métodos.Leia o nome da tag e, em seguida, leia uma contagem de operações a serem realizadas. Cada operação é uma das seguintes:
idseguido pelo valor do IDclassseguido pelo valor da classeattrseguido pelo nome e valor do atributo (duas linhas)contentseguido pelo texto do conteúdo
Encadeie todas as operações de forma fluente e, em seguida, imprima o HTML renderizado.
As seguintes entradas serão fornecidas:
- Linha 1: Nome da tag
- Linha 2: Número de operações
- Linhas seguintes: Tipo de operação e valor(es)
Por exemplo, dado:
div
3
id
container
class
main-content
content
Hello WorldSua saída deve ser:
<div class="main-content" id="container">Hello World</div>E dado:
a
3
attr
href
https://example.com
attr
target
_blank
content
Click hereSua saída deve ser:
<a href="https://example.com" target="_blank">Click here</a>E dado:
input
2
attr
type
text
attr
placeholder
Enter nameSua saída deve ser:
<input placeholder="Enter name" type="text"></input>E dado:
p
1
content
Simple paragraphSua saída deve ser:
<p>Simple paragraph</p>Observe como o encadeamento de métodos permite construir elementos passo a passo de uma forma legível. Cada método modifica o elemento e o retorna, permitindo que a próxima chamada de método seja encadeada diretamente.
Folha de consulta
O encadeamento de métodos (method chaining) é uma técnica onde os métodos retornam o receptor (geralmente *StructType), permitindo que várias chamadas de método sejam vinculadas em uma única instrução.
Cada método deve usar um receptor de ponteiro e retornar *StructType:
type Query struct {
table string
columns []string
where string
limit int
}
func (q *Query) Select(cols ...string) *Query {
q.columns = cols
return q
}
func (q *Query) From(table string) *Query {
q.table = table
return q
}
func (q *Query) Where(condition string) *Query {
q.where = condition
return q
}
func (q *Query) Limit(n int) *Query {
q.limit = n
return q
}Encadeie chamadas de método de forma fluida:
query := &Query{}
query.Select("name", "email").From("users").Where("active = true").Limit(10)O encadeamento de métodos funciona melhor quando as operações configuram ou modificam um objeto sem a necessidade de retornar outros valores. É comumente usado em construtores de consultas (query builders), APIs de configuração e bibliotecas de asserção de testes.
Experimente você mesmo
package main
import (
"bufio"
"fmt"
"os"
"strconv"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
// Ler o nome da tag
scanner.Scan()
tagName := scanner.Text()
// Ler o número de operações
scanner.Scan()
numOps, _ := strconv.Atoi(scanner.Text())
// Criar o elemento
element := NewElement(tagName)
// Processar cada operação
for i := 0; i < numOps; i++ {
scanner.Scan()
operation := scanner.Text()
// TODO: Com base no tipo de operação, encadeie o método apropriado
// As operações podem ser: "id", "class", "attr" ou "content"
// - Para "id": leia a próxima linha como o valor do ID
// - Para "class": leia a próxima linha como o valor da classe
// - Para "attr": leia as próximas DUAS linhas (nome do atributo, depois o valor)
// - Para "content": leia a próxima linha como o texto do conteúdo
// Use o encadeamento de métodos para construir o elemento de forma fluente
_ = operation // Remova esta linha ao implementar
}
// Imprimir o HTML renderizado
fmt.Println(element.Render())
}
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 Pool12Conceitos Avançados de OOP
Padrão Functional OptionsPadrão Builder em GoEncadeamento de MétodosType Aliases vs DefiniçõesFundamentos de ReflectionVisão Geral de Geração de Código