J'ai un fichier texte que j'ai lu à partir de mon programme Go. Je voudrais expédier un seul exécutable, sans fournir ce fichier texte en plus. Comment l'intégrer dans la compilation sur Windows et Linux?
Utilisez go-bindata . Du README:
Cet outil convertit n'importe quel fichier en code source Go gérable. Utile pour incorporer des données binaires dans un programme go. Les données du fichier sont éventuellement compressées au format gzip avant d'être converties en une tranche d'octets bruts.
Depuis Go 1.4, vous pouvez utiliser allez générer si vous avez besoin de plus de flexibilité.
Si vous avez plusieurs fichiers texte ou si le fichier texte peut changer, vous ne voudrez peut-être pas coder en dur le fichier texte mais l'inclure au moment de la compilation.
Si vous disposez des fichiers suivants:
main.go
scripts/includetxt.go
a.txt
b.txt
Et si vous souhaitez avoir accès au contenu de tous les fichiers .txt dans main.go, vous pouvez inclure un commentaire spécial contenant une commande go generate.
package main
import "fmt"
//go:generate go run scripts/includetxt.go
func main() {
fmt.Println(a)
fmt.Println(b)
}
La commande go generate exécutera le script après go:generate
. Dans ce cas, il exécute un script go qui lit tous les fichiers texte et les renvoie sous forme de littéraux de chaîne dans un nouveau fichier. J'ai ignoré la gestion des erreurs pour un code plus court.
package main
import (
"io"
"io/ioutil"
"os"
"strings"
)
// Reads all .txt files in the current folder
// and encodes them as strings literals in textfiles.go
func main() {
fs, _ := ioutil.ReadDir(".")
out, _ := os.Create("textfiles.go")
out.Write([]byte("package main \n\nconst (\n"))
for _, f := range fs {
if strings.HasSuffix(f.Name(), ".txt") {
out.Write([]byte(strings.TrimSuffix(f.Name(), ".txt") + " = `"))
f, _ := os.Open(f.Name())
io.Copy(out, f)
out.Write([]byte("`\n"))
}
}
out.Write([]byte(")\n"))
}
Pour compiler tous les fichiers .txt dans votre fichier exécutable:
$ go generate
$ go build -o main
Maintenant, votre structure de répertoire ressemblera à:
main.go
main
scripts/includetxt.go
textfiles.go
a.txt
b.txt
Où textfiles.go a été généré par go generate et script/includesetxt.go
package main
const (
a = `hello`
b = `world`
)
Et le fonctionnement principal donne
$ ./main
hello
world
Cela fonctionnera bien tant que vous encodez des fichiers encodés UTF8. Si vous souhaitez encoder d'autres fichiers, vous disposez de la pleine puissance de la langue go (ou de tout autre outil) pour le faire. J'ai utilisé cette technique pour encodage hexadécimal png: s en un seul exécutable. Cela nécessite une modification mineure pour inclureetet.go.
Vous pouvez utiliser un string literal
pour définir le texte comme une constante ou une variable. Les littéraux de chaîne sont définis en entourant la chaîne de guillemets. par exemple. `chaîne`.
Par exemple:
package main
import "fmt"
func main() {
const text = `
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit
amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante
hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet
vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut
libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet,
consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a
semper sed, adipiscing id dolor. Pellentesque auctor nisi id magna consequat sagittis.
Curabitur dapibus enim sit amet elit pharetra tincidunt feugiat nisl imperdiet. Ut
convallis libero in urna ultrices accumsan. Donec sed odio eros. Donec viverra mi quis
quam pulvinar at malesuada arcu rhoncus. Cum sociis natoque penatibus et magnis dis
parturient montes, nascetur ridiculus mus. In rutrum accumsan ultricies. Mauris vitae
nisi at sem facilisis semper ac in est.
`
fmt.Println(text)
}
Cherchait la même chose et est tombé sur esc: Embedding Static Assets in Go (d'ici le 19 novembre 2014) où l'auteur, Matt Jibson , évalue 3 autres packages populaires qui prétendent faire l'incorporation de fichiers:
et expliquer pourquoi il a finalement trouvé son propre package:
Donc, après les avoir tous brièvement essayés (dans cet ordre), j'ai naturellement choisi Matt esc car c'était le seul qui fonctionnait hors de la boîte avec nécessaire pour moi fonctionnalité, à savoir:
//go:generate
au lieu de vous forcer à écrire manuellement du code Go supplémentaireLe point # 2 était important pour moi et le reste des paquets pour une raison ou une autre n'a pas bien fonctionné.
Du README de l'esc:
esc intègre des fichiers dans les programmes go et leur fournit des interfaces http.FileSystem.
Il ajoute tous les fichiers nommés ou les fichiers récursivement sous les répertoires nommés au chemin spécifié. Le fichier de sortie fournit une interface http.FileSystem avec aucune dépendance sur les packages en dehors de la bibliothèque standard.
J'ai utilisé une fonction simple pour lire un modèle externe dans un cycle go generate
Et pour générer du code Go à partir de celui-ci. Une fonction renvoyant le modèle sous forme de chaîne sera générée. On peut ensuite analyser la chaîne de modèle retournée en utilisant tpl, err := template.New("myname").Parse(mynameTemplate())
J'ai mis ce code dans github. Vous voudrez peut-être essayer https://github.com/wlbr/templify
Très simple, mais fonctionne assez bien pour moi.
Sur la base du commentaire @CoreyOgburn et de cette commentaire Github , l'extrait de code suivant a été créé:
//go:generate statik -src=./html
package main
import (
_ "./statik"
"github.com/rakyll/statik/fs"
)
func statikFile() {
s, _ := fs.New() f, _ := s.Open("/tmpl/login.html") b, _ := ioutil.ReadAll(f) t, _ := template.New("login").Parse(string(b)) t.Execute(w, nil) }
et courir
go generate
et par la suite
go build
devrait créer un binaire qui contient les fichiers
check packr , son assez convivial à utiliser
package main
import (
"net/http"
"github.com/gobuffalo/packr"
)
func main() {
box := packr.NewBox("./templates")
http.Handle("/", http.FileServer(box))
http.ListenAndServe(":3000", nil)
}