Testando o novo mux no GO 1.22
Testando o mux http server em Go (Golang) no que será a versão 1.22 (1.22rc1)
Motivação
O fato da linguagem Go me lembrar muito da linguagem C a tornou muito confortável para mim. Em todo o tempo em que estudo a linguagem por hobby, uma coisa me incomoda: o uso de bibliotecas de terceiros para tarefas triviais.
A filosofia de Go vai de encontro ao meu pensamento: quanto menos bibliotecas de terceiros eu usar, melhor. Por segurança, por comodidade, por menos coisas para me preocupar, por querer uma linguagem com o máximo de "baterias inclusas".
Então sempre me deu preguiça construir APIs em Go, pois o mais fácil é utilizar algum muxer não incluso. Isso para mim é uma tarefa básica, portanto a linguagem deveria implementar da melhor maneira. Assim, cá estou eu feliz com as promessas da versão 1.22.
Infraestrutura
É preciso ter o compilador na versão correta: 1.22rc1.
Uso o asdf para gerenciar as linguagens de programação que utilizo. Com ele, basta instalar indicando a versão desejada:
asdf install golang 1.22rc1
asdf global golang 1.22rc1
asdf reshim golang
Lembrando que se não quiser tornar essa versão a utilizada globalmente, basta entrar na pasta que queira restringir a versão e executar o seguinte comando:
asdf local golang 1.22rc1
A forma normalmente indicada para versões não definitivas, é utilizar o gotip:
go install golang.org/dl/gotip@latest
gotip download
Se utilizar o gotip, em todas as situações em que dever usar o comando go, substitua por gotip, mantendo os parâmetros.
Minhas fontes
Comecei lendo o artigo de Eli Bendersky sobre isso:
https://eli.thegreenplace.net/2023/better-http-server-routing-in-go-122/
E, conforme lá indicado, dei uma olhada na documentação da linguagem:
https://pkg.go.dev/net/[email protected]#hdr-Patterns
O programa
Adaptado das fontes acima, eis:
package main
import (
"fmt"
"net/http"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("GET /path/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "got path\n")
})
mux.HandleFunc("GET /gospel/{version}/{testament}/{book}/{chapter}/", func(w http.ResponseWriter, r *http.Request) {
version := r.PathValue("version")
testament := r.PathValue("testament")
book := r.PathValue("book")
chapter := r.PathValue("chapter")
fmt.Fprintf(w, "handling gospel with version=%v, testament=%v, book=%v, chapter=%v\n", version, testament, book, chapter)
})
http.ListenAndServe("127.0.0.1:8090", mux)
}
Perceba-se que ao utilizar {book}
na configuração do endpoint, pode-se acessar a variável na posição com book := r.PathValue("book")
. Além de se poder indicar qual o verbo utilizado (nesse caso GET
). Caso se queira vários métodos para uma URL, basta omitir o verbo.
Para executar, as possibilidades, conforme se instalou a nova versão de Go. Pelo asdf, ou instalação direta:
go run server.go
Ou pelo gotip:
gotip run server.go
Executei o programa tanto em um Debian, como em um Fedora. No Fedora rolou de boas, mas no Debian simplesmenente não foi:
$ curl localhost:8090/gospel/almeida/new/marcos/3/
404 page not found
E para o outro endpoint:
$ curl localhost:8090/path/
404 page not found
Lendo os documentos acima indicados com mais atenção, descobri um parâmetro que habilita ou desabilita essa feature. COofigurando uma variável de ambiente no terminal em que o servidor é executado, tudo funciona:
$ export GODEBUG=httpmuxgo121=0
$ go run http_server.go
OU então, passando a variável na linha de execução:
$ curl localhost:8090/path/
got path
E o outro endpoint:
$ curl localhost:8090/gospel/almeida/new/marcos/3/
handling gospel with version=almeida, testament=new, book=marcos, chapter=3