2017-07-04 2 views
0

Seit einiger Zeit habe ich mich gefragt, wo ich Ressourcen für mein Go-Paket speichern kann und ich kann einfach keine richtige Antwort finden.Golang - wo sollten Ressourcen gehalten werden?

Im Moment werden die Ressourcen immer wieder in

  • main/module1/resources
  • main/module2/Ressourcen

Wenn ich nur go run *.go von Haupt verwenden es funktioniert gut. Beim Ausführen von Tests können die Ressourcen jedoch nicht gefunden werden, da Go das aktuelle Arbeitsverzeichnis in das entsprechende Modul ändert. Ein Workaround ist, nur os.Chdir ('..'), aber das für jeden Test scheint irgendwie nervig. Außerdem werden manchmal die Ressourcen geladen, wenn das Paket initialisiert wird. Das heißt, es ist eine globale Karte mit allen Vorlagen (und den zugehörigen Namen):

package module2 

var myTemplates = map[string]template { "index": loadTemplateFromFile() } 

Ich weiß, Sie sollten nicht Globals in gehen, weil die Parallelität verwenden, aber diese Variable ist sicher für die gleichzeitig liest (und es ist nur während des Startvorgangs geschrieben). Also lege ich die Templates in eine globale Variable, so dass sie beim Start geladen werden können und einige Fehler beim Starten gefangen werden und die Vorlage bereits im Speicher ist.

Das bedeutet, dass ich das Arbeitsverzeichnis nicht rechtzeitig ändern kann, da das Problem bereits mit einem Fehler in Panik geraten ist und mir mitgeteilt wurde, dass die Datei nicht gefunden werden konnte (dies ist das genaue Verhalten, das ich möchte).

Später entdeckte ich eine Methode runtime.Caller aus dem Weg zu bekommen, wo die gehen Dateien kompiliert wurden (falls vorhanden):

base := "." 
if _, filename, _, ok := runtime.Caller(0); ok { 
    base = path.Join(path.Dir(filename), "..") 
} 
file := path.Join(base, "module1", "resources", ...) 

nun alle Tests gut funktionieren und go run *.go findet auch die richtigen Ressourcen. Diese Methode wird zu einem Problem, sobald ich mit der Bereitstellung meines Pakets beginne. Da runtime.Caller den Pfad verwendet, der beim Kompilieren verwendet wurde, muss ich die Ressourcen am selben Ort haben, an dem ich sie erfüllt habe. Das heißt, wenn ich die Binärdatei in /home/matt3o12/go/src/domain.tld/matt3o12/mypackage erstelle, muss ich alle Ressourcenordner auf dem gleichen Pfad auf dem Server haben.

Ich habe auch versucht, os.Executable zu verwenden, aber das ist ziemlich sinnlos, da es nur auf einen temporären Pfad mit der kompilierten ausführbaren Datei zeigt (und keine Ressourcen). Es sei denn, ich kompiliere ein Testpaket und führe es manuell aus, aber das ist sehr arbeitsintensiv.

Ich bin auch nicht auf der Suche nach den Ressourcen innerhalb der Binärdatei zu speichern (mit einer Ordnerstruktur der Projektressourcen ist ganz in Ordnung).

Ich habe einige Ideen haben, dieses Problem zu lösen, aber ich glaube nicht, dass von ihnen sind optional:

  • Verwenden Sie ein Flag in den Ressourcenordner zu zeigen. Das würde funktionieren, aber das für jeden Test zu verwenden, wäre ziemlich nervig (weil ich jetzt jedes Mal, wenn ich go test ./... oder go run *.go verwende, mich um den richtigen Ressourcenpfad kümmern muss).
  • Verwenden Sie "Magie", um herauszufinden, ob Tests ausgeführt werden, und ändern Sie den Pfad entsprechend. Ich würde es hassen, das zu verwenden, weil ich diese Schecks überall auf meinem Code platzieren müsste und ich hasse es, viele "Rand-/Spezialfälle" zu haben.

Diese ist nicht ein Duplikat:

+0

siehe https://github.com/jteeuwen/go-bindata oder andere ähnliche Optionen zum Packen Ihrer Ressourcen in die ausführbare Datei – superfell

+0

Sehen Sie einige Ideen in diesem möglichen Duplikat: [wie man eine relative Datei aus Code und Tests referenziert] (https://stackoverflow.com/questions/31059023/how-to-reference-a-relative-file -from-code-and-tests/31059125 # 31059125). – icza

+0

@superfell Ich bin mir der Go-Bindata bewusst, aber das ist nicht das, was ich gesucht habe. Ich möchte keine Daten in Go-Quelldateien speichern. – Matt3o12

Antwort

0

Es n o "sollte". Sie können sie dort platzieren, wo Sie es für richtig halten. Sie können sie einbetten, wenn Sie möchten. Am einfachsten ist es wahrscheinlich, den Pfad zu Ihren Ressourcen mit einigen vernünftigen Standardeinstellungen zu konfigurieren (wie standardmäßig "." Oder runtime.Caller(0).

Verwandte Themen