Minha Aventura pelo Mundo Go: Simplicidade que Conquista
- #Kotlin
- #Node.js
- #Cloud
- #GoLang
- #API Rest
O que me trouxe até aqui
Sempre fui fascinado por tecnologia e desenvolvimento. Minha jornada começou com Java, onde aprendi os conceitos básicos de programação. Em seguida, migrei para o frontend com HTML, CSS e JavaScript, explorando a construção de interfaces. Foi então que mergulhei no mundo do backend web, onde conheci as facilidades e ferramentas que o Node.js oferece, e tive meus encontros com Java novamente e me apaixonei pelo Kotlin.
Essas experiências foram fundamentais para minha formação como desenvolvedor. O ecossistema Node me ensinou sobre assincronicidade e a flexibilidade de usar a mesma linguagem no frontend e backend. Java e Spring me apresentaram a arquiteturas robustas e design patterns que carrego comigo até hoje.
Mas em certos projetos, eu buscava algo com uma abordagem diferente. Foi quando esbarrei com Go.
Go: O encanto da simplicidade
O que inicialmente me chamou atenção no Go? Confesso que a cor azul do mascote teve seu papel (sim, sou facilmente influenciável por uma boa identidade visual). Mas o que realmente me conquistou foi sua proposta: simplicidade e performance.
Estou finalizando a Formação Go Developer na DIO, e ao longo desse percurso, percebi que a linguagem oferece uma perspectiva interessante. Não necessariamente melhor que Node.js ou Java/Kotlin em todos os aspectos, mas diferente e adequada para certas situações e preferências pessoais.
O Spring Boot tem seu imenso valor - é poderoso e elegante, com uma estrutura que resolve problemas complexos com sofisticação. Já o ecossistema Node brilha por sua flexibilidade extrema, permitindo construir praticamente qualquer coisa de inúmeras maneiras. Para grandes projetos corporativos ou aplicações que precisam escalar rapidamente em funcionalidades, eles são frequentemente escolhas excelentes.
Go: Uma abordagem alternativa para certas dores de cabeça
Uma das coisas que me atraiu ao Go foi como ele oferece uma abordagem diferente para alguns desafios do desenvolvimento diário.
Uma relação diferente com dependências
O npm e o Maven/Gradle são ferramentas poderosas de gerenciamento de pacotes. Esses ecossistemas são incrivelmente ricos e facilitam a construção rápida de funcionalidades complexas.
Em alguns projetos menores, no entanto, a abordagem mais contida do Go traz uma simplicidade refrescante:
// Um servidor HTTP simples em Go usando apenas a biblioteca padrão
package main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Olá, %s!", r.URL.Path[1:])
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
O pacote net/http é uma das coisas que mais me impressionou no Go. É incrível como conseguir criar servidores de forma tão leve e direta, sem precisar instalar dezenas de pacotes. A biblioteca padrão do Go já traz muitas funcionalidades úteis que, em outros ecossistemas, exigiriam dependências externas.
Alternativa leve à JVM
A JVM é uma plataforma robusta que possibilitou muitos dos sistemas que utilizamos diariamente. Kotlin não existiria sem essa base sólida.
Contudo, para microserviços e utilitários mais leves, a abordagem do Go se mostra particularmente interessante:
// Um exemplo de concorrência em Go
package main
import (
"fmt"
"time"
)
func tarefa(nome string) {
for i := 0; i < 3; i++ {
fmt.Println(nome, ":", i)
time.Sleep(time.Millisecond * 500)
}
}
func main() {
// Inicia duas goroutines (threads leves)
go tarefa("Tarefa A")
go tarefa("Tarefa B")
// Espera para ver os resultados
time.Sleep(time.Second * 2)
}
Não se trata de a JVM ser inadequada, mas de ter opções dimensionadas para diferentes tipos de problemas. Para certas aplicações, os executáveis compactos e a inicialização rápida do Go trazem vantagens práticas.
Encontrando o equilíbrio na abstração
Spring Boot me ensinou muito sobre design de software e injeção de dependências. A elegância que ele traz com suas anotações tem seu lugar de destaque em grandes sistemas empresariais.
Para projetos onde prefiro mais controle explícito sobre o fluxo, a abordagem do Go oferece uma clareza interessante:
// Uma API REST simples em Go
package main
import (
"encoding/json"
"log"
"net/http"
)
type Mensagem struct {
Texto string `json:"texto"`
}
func apiHandler(w http.ResponseWriter, r *http.Request) {
// Retorna uma resposta JSON simples
msg := Mensagem{Texto: "API funcionando!"}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(msg)
}
func main() {
http.HandleFunc("/api", apiHandler)
log.Println("Servidor iniciado na porta 8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
É uma questão de preferência para cada contexto específico. Às vezes o código mais explícito facilita o entendimento do fluxo completo da aplicação.
Programação ao meu estilo
O que me atrai no Go é como ele se alinha com certas preferências pessoais em determinados contextos. Mas como todo relacionamento com tecnologias, também tive minhas dificuldades iniciais.
Uma das coisas que mais senti falta no início foram as arrow functions e expressões lambda que uso frequentemente em Node.js e Kotlin. O .map(), .filter() e outras operações funcionais são ferramentas que me caíram muito bem, e o Go tem uma abordagem diferente nesse aspecto. Com o tempo, acabei me adaptando a um estilo mais imperativo para essas operações.
Como programador, tenho a liberdade de escolher diferentes ferramentas para diferentes problemas. Go se junta ao meu arsenal não para substituir as outras tecnologias, mas para complementá-las.
O prazer do código explícito (com seus prós e contras)
Em Go, encontrei uma abordagem que, para certos projetos, traz uma clareza bem-vinda.
// Manipulação de erros explícita em Go
func dividir(a, b float64) (float64, error) {
if b == 0 {
return 0, errors.New("divisão por zero não permitida")
}
return a / b, nil
}
func main() {
resultado, err := dividir(10, 0)
if err != nil {
fmt.Println("Erro:", err)
return
}
fmt.Println("Resultado:", resultado)
}
Esse padrão de verificação de erro é interessante conceitualmente, pois os erros são tratados como valores e não como exceções especiais. No entanto, o famoso if err != nil
acaba se repetindo tanto que bem que poderia existir uma sintaxe açucarada para essa verificação tão comum. Existem debates na comunidade Go sobre isso, e talvez vejamos evoluções nessa área no futuro.
Não é uma questão de superioridade sobre o try/catch, mas de diferentes filosofias com seus próprios méritos e desafios.
O caminho pela frente
Ainda estou no começo dessa jornada com Go, adicionando-o ao meu conjunto de habilidades. Cada tecnologia traz sua própria perspectiva sobre como resolver problemas, e Go traz uma ênfase na clareza e objetividade que tem seu valor.
O ecossistema Go pode não ser tão vasto quanto Node.js, nem tão maduro quanto Java, e isso é perfeitamente ok. Cada tecnologia tem seu propósito e seu conjunto único de vantagens e desvantagens.
Para quem estiver curioso sobre Go, minha dica é: experimente-o como mais uma ferramenta no seu arsenal, não como um substituto para tudo que veio antes. A diversidade de abordagens nos torna desenvolvedores mais completos.
Agora tô realmente empolgado para ver o que posso criar com Go e como ele complementará minhas experiências anteriores nessa contínua jornada de aprendizado.