Paulo Henrique Rodrigues Pinheiro

Um blog sobre programação para programadores!


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)

Imagem criada no Bing Image Creator com o prompt golang mux http server estilo goya

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