Ich arbeite an einer kleinen Webanwendung in Go, die als Tool auf dem Computer eines Entwicklers verwendet werden soll, um das Debuggen seiner Anwendungen / Webdienste zu unterstützen. Die Schnittstelle zum Programm ist eine Webseite, die nicht nur HTML, sondern auch JavaScript (für die Funktionalität), Bilder und CSS (für das Styling) enthält. Ich plane, diese Anwendung als Open-Sourcing-Lösung zu verwenden, damit Benutzer einfach ein Makefile ausführen können und alle Ressourcen dorthin gelangen, wo sie benötigt werden. Ich möchte aber auch einfach eine ausführbare Datei mit so wenig Dateien / Abhängigkeiten wie möglich verteilen können. Gibt es eine gute Möglichkeit, HTML / CSS / JS mit der ausführbaren Datei zu bündeln, sodass Benutzer nur eine Datei herunterladen und sich um sie kümmern müssen?
Im Moment sieht das Bereitstellen einer statischen Datei in meiner App ungefähr so aus:
// 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
}
Es ist also ziemlich einfach: Wenn die angeforderte Datei in meinem statischen Verzeichnis vorhanden ist, rufen Sie den Handler auf, der die Datei einfach öffnet und versucht, Content-Type
vor dem Serving ein Gut festzulegen. Mein Gedanke war, dass es keinen Grund gibt, warum dies auf dem realen Dateisystem basieren muss: Wenn es kompilierte Ressourcen gäbe, könnte ich sie einfach anhand der Anforderungs-URI indizieren und als solche dienen.
Wenn es keinen guten Weg gibt, dies zu tun, oder ich den falschen Baum belle, indem ich versuche, dies zu tun, lassen Sie es mich wissen. Ich dachte nur, der Endbenutzer würde es begrüßen, wenn so wenig Dateien wie möglich verwaltet werden könnten.
Wenn es passendere Tags als gibt gehen, zögern Sie nicht, sie hinzuzufügen oder lassen Sie es mich wissen.
go generate
, die Dateien mit einem kleinen Befehlszeilenprogramm (zusammen mit meinem Quellcode) in[]byte
Slices zu konvertieren, die als Variablen in den Code eingebettet sind, ähnlich wie dies derstringer
Fall ist (siehe blog.golang.org) / generieren ).Antworten:
Das go-bindata-Paket scheint das zu sein, woran Sie interessiert sind.
https://github.com/go-bindata/go-bindata
Damit können Sie jede statische Datei in einen Funktionsaufruf konvertieren, der in Ihren Code eingebettet werden kann, und beim Aufruf ein Byte-Slice des Dateiinhalts zurückgeben.
quelle
Einbetten von Textdateien
Wenn es sich um Textdateien handelt, können diese problemlos in den Quellcode selbst eingebettet werden. Verwenden Sie einfach die hinteren Anführungszeichen, um das
string
Literal wie folgt zu deklarieren :Optimierungstipp:
Da Sie die Ressource in den meisten Fällen nur in eine schreiben müssen
io.Writer
, können Sie auch das Ergebnis einer[]byte
Konvertierung speichern :Sie müssen nur vorsichtig sein, dass rohe String-Literale das hintere Anführungszeichen (`) nicht enthalten dürfen. Raw-String-Literale dürfen keine Sequenzen enthalten (im Gegensatz zu den interpretierten String-Literalen). Wenn der einzubettende Text also Anführungszeichen enthält, müssen Sie das Raw-String-Literal aufbrechen und Back-Anführungszeichen als interpretierte String-Literale verketten, wie in diesem Beispiel:
Die Leistung wird nicht beeinträchtigt, da diese Verkettungen vom Compiler ausgeführt werden.
Einbetten von Binärdateien
Speichern als Byte-Slice
Für Binärdateien (z. B. Bilder) wäre es am kompaktesten (in Bezug auf die resultierende native Binärdatei) und am effizientesten, den Inhalt der Datei
[]byte
in Ihrem Quellcode zu haben. Dies kann von Toos / Bibliotheken von Drittanbietern wie go-bindata generiert werden .Wenn Sie hierfür keine Bibliothek eines Drittanbieters verwenden möchten, finden Sie hier ein einfaches Codefragment, das eine Binärdatei liest und Go-Quellcode ausgibt, der eine Variable vom Typ deklariert
[]byte
, die mit dem genauen Inhalt der Datei initialisiert wird:Beispielausgabe, wenn die Datei Bytes von 0 bis 16 enthalten würde (versuchen Sie es auf dem Go Playground ):
Speichern als base64
string
Wenn die Datei nicht "zu groß" ist (die meisten Bilder / Symbole sind qualifiziert), gibt es auch andere praktikable Optionen. Sie können den Inhalt der Datei in eine Base64 konvertieren
string
und in Ihrem Quellcode speichern. Beim Start der Anwendung (func init()
) oder bei Bedarf können Sie sie in den ursprünglichen[]byte
Inhalt dekodieren . Go bietet eine gute Unterstützung für die Base64-Codierung imencoding/base64
Paket.Das Konvertieren einer (binären) Datei in base64
string
ist so einfach wie:Speichern Sie die Ergebnis-Base64-Zeichenfolge in Ihrem Quellcode, z
const
. B. als .Das Dekodieren ist nur ein Funktionsaufruf:
Lagerung wie angegeben
string
Effizienter als Base64 speichern, aber mehr im Quellcode kann sein wird , um die Speicherung zitierte Stringliteral der binären Daten. Wir können die zitierte Form jeder Zeichenfolge mit der folgenden
strconv.Quote()
Funktion erhalten:Bei Binärdaten mit Werten von 0 bis 64 würde die Ausgabe folgendermaßen aussehen (versuchen Sie es auf dem 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:;<=>?"
(Beachten Sie, dass
strconv.Quote()
ein Anführungszeichen angehängt und vorangestellt wird.)Sie können diese Zeichenfolge in Anführungszeichen direkt in Ihrem Quellcode verwenden, zum Beispiel:
Es ist gebrauchsfertig und muss nicht dekodiert werden. Das Aufheben der Anführungszeichen erfolgt durch den Go-Compiler zur Kompilierungszeit.
Sie können es auch als Byte-Slice speichern, wenn Sie es so benötigen:
quelle
sh
Datei an eine ausführbare Datei zu binden ?Es gibt auch eine exotische Möglichkeit: Ich verwende das Maven-Plugin , um GoLang-Projekte zu erstellen, und es ermöglicht die Verwendung des JCP-Präprozessors zum Einbetten von Binärblöcken und Textdateien in Quellen. Im Fallcode sehen Sie einfach wie in der Zeile unten aus ( und ein Beispiel finden Sie hier )
quelle
sh
oder einer ausführbaren Datei wie oben zu bindensh
Datei binden ? Nicht sicher was du meinst. Wenn Sie möchten, dass alles in einem Verzeichnis eingebettet wird, habe ich dies getango-bindata
. Wenn ich beispielsweise//go:generate $GOPATH/bin/go-bindata -prefix=data/ -pkg=$GOPACKAGE data/
eine (nicht generierte) go-Dateigo generate ./...
eingebe , wird go-bindata im Paketverzeichnis ausgeführt und alles in ein Daten-Unterverzeichnis eingebettet, wobei das Präfix 'data /' entfernt wird.Als beliebte Alternative zu einer
go-bindata
anderen Antwort bettet mjibson / esc auch beliebige Dateien ein, behandelt Verzeichnisbäume jedoch besonders bequem.quelle