Je voulais créer une petite application Web autonome dans Go, à l'opposé d'une application Web classique où les ressources seraient servies séparément via un serveur CDN ou HTTP tel que Nginx.
Toutefois, si les performances ne constituent pas une préoccupation critique ou si l'application est destinée à un faible trafic, l'utilisation d'une application autonome simplifie le déploiement et la distribution car il s'agit simplement d'un binaire exécutable.
Plusieurs packages sont disponibles pour intégrer des ressources dans une application Go :
Je n'entrerai pas dans les spécificités de chaque bibliothèque, mais je préfère l'approche bindata en raison de sa facilité d'utilisation et de son support actif.
Tout d'abord, créons un index.html
dans le répertoire frontend/
de votre projet :
<html> <body> Hello, World! </body> </html>
Maintenant que nous avons une configuration de projet et une ressource statique à tester, installons bindata à l'aide de la commande :
go get -u github.com/jteeuwen/go-bindata/...
Nous sommes prêts à exécuter le code backend de l'application Web. Créez un fichier main.go
et copiez le code suivant :
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) }
Ligne importante dans ce code :
//go:generate go-bindata -prefix "frontend/" -pkg main -o bindata.go frontend/...
La ligne ci-dessus nous permet d'exécuter la commande go-bindata
lorsque go generate
est appelé. Depuis la version 1.4, vous pouvez exécuter des commandes personnalisées pendant la phase de génération. Il s'agit simplement d'ajouter //go:generate command argument...
à votre fichier go.
La ligne de commande go-bindata
a plusieurs paramètres, alors consultez la documentation pour savoir comment l'utiliser. Dans notre cas, nous disons :
-prefix "frontend/"
définit une partie du chemin d'accès pour le statique
-pkg main
définit le nom du package utilisé dans le code généré
-o bindata.go
définit le nom du fichier généré
Après avoir exécuté la commande go generate
, vous devriez voir un fichier généré nommé bindata.go
. La structure de votre projet devrait ressembler à ceci :
. │ ├── bindata.go (auto-generated file) ├── frontend │ └── index.html └── main.go
La logique de service des fichiers statiques se trouve dans la fonction static_handler
, qui reçoit la demande et vérifie si le chemin correspond au chemin statique. La vérification se fait à l'aide de la fonction Asset
, automatiquement exportée par l'utilisateur bindata.go
. Si la ressource n'existe pas, on renvoie un 404
, sinon, on renvoie le contenu de la ressource.
Le reste du code sert à créer l'application Web et à lier notre modèle static_handler
pour qu'il corresponde à toutes les demandes entrantes pour /
. Si vous avez du mal à comprendre ce code, consultez la documentation officielle Go pour http package
.
Pour rappel rapide de la façon dont Go gère les packages, tous les identifiants seront automatiquement exportés vers d'autres packages portant le même nom si la première lettre du nom de l'identifiant commence par une lettre majuscule.
Sur la base de cette règle, le fichier bindata.go
fournit la fonction Asset
pour le package main
. Cela charge et renvoie un actif pour le nom donné. Il renvoie une erreur si la ressource est introuvable ou ne peut pas être chargée.