Je travaille sur une petite application Web dans Go qui est destinée à être utilisée comme un outil sur la machine d'un développeur pour aider à déboguer leurs applications / services Web. L'interface du programme est une page Web qui comprend non seulement le HTML, mais aussi du JavaScript (pour la fonctionnalité), des images et du CSS (pour le style). Je prévois d'ouvrir cette application, donc les utilisateurs devraient simplement pouvoir exécuter un Makefile et toutes les ressources iront là où elles doivent aller. Cependant, j'aimerais aussi pouvoir distribuer simplement un exécutable avec le moins de fichiers / dépendances possible. Existe-t-il un bon moyen de regrouper le HTML / CSS / JS avec l'exécutable, afin que les utilisateurs n'aient qu'à télécharger et à se soucier d'un seul fichier?
À l'heure actuelle, dans mon application, servir un fichier statique ressemble un peu à ceci:
// called via http.ListenAndServe
func switchboard(w http.ResponseWriter, r *http.Request) {
// snipped dynamic routing...
// look for static resource
uri := r.URL.RequestURI()
if fp, err := os.Open("static" + uri); err == nil {
defer fp.Close()
staticHandler(w, r, fp)
return
}
// snipped blackhole route
}
C'est donc assez simple: si le fichier demandé existe dans mon répertoire statique, invoquez le gestionnaire, qui ouvre simplement le fichier et essaie de définir un bon Content-Type
avant de servir. Ma pensée était qu'il n'y avait aucune raison que cela doive être basé sur le système de fichiers réel: s'il y avait des ressources compilées, je pourrais simplement les indexer par l'URI de la requête et les servir comme telles.
S'il n'y a pas une bonne façon de faire cela, ou si j'aboie le mauvais arbre en essayant de le faire, faites-le moi savoir. J'ai juste pensé que l'utilisateur final apprécierait le moins de fichiers possible à gérer.
S'il y a des balises plus appropriées que aller, n'hésitez pas à les ajouter ou à me le faire savoir.
go generate
avec un petit utilitaire de ligne de commande (fourni avec mon code source) pour convertir les fichiers en[]byte
tranches qui sont incorporées en tant que variables dans le code, de la même manièrestringer
(voir blog.golang.org / générer ).Réponses:
Le package go-bindata semble être ce qui vous intéresse.
https://github.com/go-bindata/go-bindata
Il vous permettra de convertir n'importe quel fichier statique en un appel de fonction qui peut être incorporé dans votre code et renverra une tranche d'octet du contenu du fichier lorsqu'il est appelé.
la source
Incorporation de fichiers texte
Si nous parlons de fichiers texte, ils peuvent facilement être intégrés dans le code source lui-même. Utilisez simplement les guillemets pour déclarer le
string
littéral comme ceci:Conseil d'optimisation:
Comme la plupart du temps, vous n'aurez qu'à écrire la ressource dans un
io.Writer
, vous pouvez également stocker le résultat d'une[]byte
conversion:La seule chose à laquelle vous devez faire attention est que les littéraux de chaîne bruts ne peuvent pas contenir le caractère guillemet arrière (`). Les littéraux de chaîne bruts ne peuvent pas contenir de séquences (contrairement aux littéraux de chaîne interprétés), donc si le texte que vous souhaitez incorporer contient des guillemets, vous devez casser le littéral de chaîne brute et concaténer les guillemets arrière comme des littéraux de chaîne interprétés, comme dans cet exemple:
Les performances ne sont pas affectées, car ces concaténations seront exécutées par le compilateur.
Incorporation de fichiers binaires
Stockage sous forme de tranche d'octet
Pour les fichiers binaires (par exemple des images), le plus compact (en ce qui concerne le binaire natif résultant) et le plus efficace serait d'avoir le contenu du fichier comme un
[]byte
dans votre code source. Cela peut être généré par des toos / bibliothèques tiers comme go-bindata .Si vous ne souhaitez pas utiliser une bibliothèque tierce pour cela, voici un simple extrait de code qui lit un fichier binaire et génère un code source Go qui déclare une variable de type
[]byte
qui sera initialisée avec le contenu exact du fichier:Exemple de sortie si le fichier contiendrait des octets de 0 à 16 (essayez-le sur le Go Playground ):
Stockage en base64
string
Si le fichier n'est pas «trop volumineux» (la plupart des images / icônes sont admissibles), il existe également d'autres options viables. Vous pouvez convertir le contenu du fichier en Base64
string
et le stocker dans votre code source. Au démarrage de l'application (func init()
) ou si nécessaire, vous pouvez le décoder dans le[]byte
contenu d' origine . Go a un bon support pour l'encodage Base64 dans leencoding/base64
package.La conversion d'un fichier (binaire) en base64
string
est aussi simple que:Stockez la chaîne résultat base64 dans votre code source, par exemple sous forme de fichier
const
.Le décoder est juste un appel de fonction:
Stockage comme indiqué
string
Plus efficace que le stockage en base64, mais peut être plus long dans le code source, il stocke le littéral de chaîne entre guillemets des données binaires. Nous pouvons obtenir la forme citée de n'importe quelle chaîne en utilisant la
strconv.Quote()
fonction:Pour les données binaires contenant des valeurs de 0 à 64, voici à quoi ressemblerait la sortie (essayez-la sur le Go Playground ):
"\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?"
(Notez que cela
strconv.Quote()
ajoute et ajoute un guillemet.)Vous pouvez utiliser directement cette chaîne entre guillemets dans votre code source, par exemple:
Il est prêt à l'emploi, pas besoin de le décoder; la suppression des guillemets est effectuée par le compilateur Go, au moment de la compilation.
Vous pouvez également le stocker sous forme de tranche d'octets si vous en avez besoin comme ça:
la source
sh
fichier à un exécutable go?il y a aussi une manière exotique - j'utilise le plugin maven pour construire des projets GoLang et cela permet d'utiliser le préprocesseur JCP pour incorporer des blocs binaires et des fichiers texte dans les sources. Dans le cas, le code ressemble à la ligne ci-dessous ( et un exemple peut être trouvé ici )
la source
sh
ou un exécutable comme cish
fichier? Pas sûr de ce que vous voulez dire. Si vous voulez que tout dans un répertoire soit intégré, c'est quelque chose que j'ai faitgo-bindata
. Par exemple, si je place//go:generate $GOPATH/bin/go-bindata -prefix=data/ -pkg=$GOPACKAGE data/
un fichier go (non généré),go generate ./...
j'exécute go-bindata dans le répertoire du package, en intégrant tout dans un sous-répertoire de données mais avec le préfixe «data /» supprimé.En tant qu'alternative populaire à celle
go-bindata
mentionnée dans une autre réponse, mjibson / esc intègre également des fichiers arbitraires, mais gère les arborescences de répertoires de manière particulièrement pratique.la source