paint-brush
Como incorporar recursos estáticos em um projeto Gopor@kibizovd
646 leituras
646 leituras

Como incorporar recursos estáticos em um projeto Go

por David Kibizov3m2023/11/28
Read on Terminal Reader

Muito longo; Para ler

Usar um aplicativo independente simplifica a implantação e distribuição porque é apenas um binário executável. Rice, Statik e Bindata estão disponíveis para incorporar recursos em um aplicativo Go. Vamos criar um modelo index.html e testá-lo com um recurso estático para testar o código Go.
featured image - Como incorporar recursos estáticos em um projeto Go
David Kibizov HackerNoon profile picture

Eu queria criar um pequeno aplicativo da web independente em Go, o oposto de um aplicativo da web normal, onde os recursos seriam servidos separadamente por meio de um CDN ou servidor HTTP, como o Nginx.


No entanto, se o desempenho não for uma preocupação crítica ou se o aplicativo for destinado a baixo tráfego, o uso de um aplicativo independente simplifica a implantação e a distribuição porque é apenas um binário executável.


Vários pacotes estão disponíveis para incorporar recursos em um aplicativo Go:



Não vou me aprofundar nas especificidades de cada biblioteca, mas prefiro a abordagem bindata devido à sua facilidade de uso e suporte ativo.

Começando

Primeiro, vamos criar um index.html dentro do diretório frontend/ do seu projeto:

 <html> <body> Hello, World! </body> </html>


Agora que temos a configuração do projeto e um recurso estático para testar, vamos instalar o bindata usando o comando:

 go get -u github.com/jteeuwen/go-bindata/...


Estamos prontos para executar o código backend da aplicação web. Crie um arquivo main.go e copie o seguinte código:

 package main import ( "bytes" "io" "net/http" ) //go:generate go-bindata -prefix "frontend/" -pkg main -o bindata.go frontend/... func static_handler(rw http.ResponseWriter, req *http.Request) { var path string = req.URL.Path if path == "" { path = "index.html" } if bs, err := Asset(path); err != nil { rw.WriteHeader(http.StatusNotFound) } else { var reader = bytes.NewBuffer(bs) io.Copy(rw, reader) } } func main() { http.Handle("/", http.StripPrefix("/", http.HandlerFunc(static_handler))) http.ListenAndServe(":3000", nil) }


Linha importante neste código:

 //go:generate go-bindata -prefix "frontend/" -pkg main -o bindata.go frontend/...


A linha acima nos permite executar o comando go-bindata quando go generate é chamado. A partir da versão 1.4, você pode executar comandos personalizados durante a fase de geração. É apenas uma questão de adicionar //go:generate command argument... ao seu arquivo go.


A linha de comando go-bindata possui vários parâmetros, portanto verifique a documentação sobre como utilizá-la. No nosso caso, dizemos:


  • -prefix "frontend/" define parte do nome do caminho para estático


  • -pkg main define o nome do pacote usado no código gerado


  • -o bindata.go define o nome do arquivo gerado


Depois de executar o comando go generate , você deverá ver um arquivo gerado chamado bindata.go . A estrutura do seu projeto deve ficar assim:

 . │ ├── bindata.go (auto-generated file) ├── frontend │ └── index.html └── main.go


A lógica para servir arquivos estáticos está na função static_handler , que recebe a solicitação e verifica se o caminho corresponde ao caminho estático. A verificação é feita através da função Asset , exportada automaticamente pelo usuário bindata.go . Se o recurso não existir, retornamos 404 , caso contrário, retornamos o conteúdo do recurso.


O restante do código é para criar o aplicativo da web e vincular nosso modelo static_handler para corresponder a todas as solicitações recebidas para / . Se você tiver problemas para entender esse código, verifique a documentação oficial do Go para http package .


Como um rápido lembrete de como Go lida com pacotes, todos os identificadores serão automaticamente exportados para outros pacotes com o mesmo nome se a primeira letra do nome do identificador começar com letra maiúscula.


Com base nesta regra, o arquivo bindata.go fornece a função Asset para o pacote main . Isso carrega e retorna um ativo para o nome fornecido. Ele retorna um erro se o recurso não puder ser encontrado ou carregado.