Chaining de métodos é uma técnica muito utilizada em linguagens como PHP, Java e C#. Se você não está familiarizado com o termo, não se preocupe, pois essa é uma técnica muito simples. Ela consiste em retornar um objeto para que outro método possa ser chamado sem a necessidade de atribuição a uma outra variável.
Essa técnica é muito utilizada em ORMs como o GORM, para construção de queries mais complexas.
No vídeo que postamos no nosso canal do youtube mostrando como construir uma API completa com go-chi e postgres (link para o vídeo), também podemos ver essa técnica sendo utilizada para fazer o decode da request para uma struct.
Para entender melhor seu funcionamento, vamos criar uma struct com 100% de seus atributos privados.
type Pessoa struct {
nome string
sobrenome string
idade uint
}
Agora, para que seja possível atribuir valores a esses atributos, vamos implementar um método Set para cada um deles.
func (p *Pessoa) SetNome(nome string) {
p.nome = nome
}
func (p *Pessoa) SetSobrenome(sobrenome string) {
p.sobrenome = sobrenome
}
func (p *Pessoa) SetIdade(idade uint) {
p.idade = idade
}
Para finalizar, vamos adicionar um método para fazer print das informações em forma de uma frase.
func (p *Pessoa) Print() {
fmt.Printf("Olá, meu nome é %s %s e eu tenho %d anos.", p.nome, p.sobrenome, p.idade)
}
Da forma como fizemos, para utilizar essa struct, teríamos um código similar a esse.
p := Pessoa{}
p.SetNome("Tiago")
p.SetSobrenome("Temporin")
p.SetIdade(32)
p.Print()
Porém, se quisermos chamar os métodos de forma encadeada, ou seja, fazer um chaining de chamadas, precisamos fazer uma pequena mudança nos nossos métodos Set.
Essa mudança consiste basicamente em retornar o ponteiro da struct, ou seja, retornar o p.
func (p *Pessoa) SetNome(nome string) *Pessoa {
p.nome = nome
return p
}
func (p *Pessoa) SetSobrenome(sobrenome string) *Pessoa {
p.sobrenome = sobrenome
return p
}
func (p *Pessoa) SetIdade(idade uint) *Pessoa {
p.idade = idade
return p
}
Isso não nos impede de utilizar a struct da mesma forma como já vimos, porém adiciona também a possibilidade de utilizarmos ela da seguinte forma.
p := Pessoa{}
p.SetNome("Tiago").
SetSobrenome("Temporin").
SetIdade(32).
Print()
Embora essa técnica possa deixar nosso código mais limpo, ela também pode trazer um grande problema em Go, que é o tratamento de erros.
Nas linguagens citadas no inicio, quando um erro ocorre, uma excessão é lançada e a sequencia de chamadas é quebrada, ou seja, a execução do chaining para.
Como não temos excessões em Go, para utilizar a técnica de chaining, os métodos só podem retornar o ponteiro da struct, evitando assim que possamos fazer um tratamento de erro adequado.
Meu conselho? Caso deseje utilizar essa técnica, faça-o somente em métodos simples, locais onde não existe a possibilidade de erro, ou seja, métodos do tipo Set ou preparatórios.
Dessa forma conseguimos utilizar essa técnica e ainda continuar com uma boa qualidade no tratamento de erros.
Deixem suas dúvidas nos comentários.
Até a próxima!
Faça parte da comunidade!
Receba os melhores conteúdos sobre Go, Kubernetes, arquitetura de software, Cloud e esteja sempre atualizado com as tendências e práticas do mercado.
Livros Recomendados
Abaixo listei alguns dos melhores livros que já li sobre GO.




