Etwas inspiriert von diesem Artikel in der letzten Woche, spiele ich mit dem Refactoring einer Anwendung Ich muss den Kontext (DB-Pools, Sitzungsspeicher usw.) explizit an meine Handler weitergeben.
Ein Problem, das ich habe, ist jedoch, dass ohne eine globale Vorlagenzuordnung die ServeHTTP
-Methode für meinen benutzerdefinierten Handlertyp (um http.Handler
zu erfüllen) nicht mehr auf die Map zugreifen kann, um eine Vorlage zu rendern.
Ich muss entweder die globale Variable templates
beibehalten oder meinen benutzerdefinierten Handlertyp als Struktur neu definieren.
Gibt es einen besseren Weg, dies zu erreichen?
func.go
%Vor%struct.go
%Vor% Gibt es eine sauberere Methode, die context
-Instanz an ServeHTTP
zu übergeben?
Beachten Sie, dass go build -gcflags=-m
zeigt, dass keine der beiden Optionen in Heapzuweisungs-Teams schlechter ist: Das &appContext
Literal tritt in beiden Fällen (wie erwartet) in den Heapspeicher zurück, obwohl die struct-basierte Option meiner Interpretation entspricht Übergeben Sie bei jeder Anfrage einen zweiten Zeiger (an context
) - Korrigieren Sie mich, wenn ich hier falsch liege , denn ich würde es lieben, dies besser zu verstehen.
Ich bin nicht ganz davon überzeugt, dass Globals im Paket main (dh nicht lib) schlecht sind, vorausgesetzt, dass sie auf diese Weise sicher sind (read only / mutexes / a pool), aber ich mag Klarheit, die ich explizit weitergeben muss Kontext bietet.
Nach einigen Diskussionen mit ein paar hilfreichen Gophern auf # go-nuts, geht es bei der obigen Methode um "so gut wie es geht" von dem, was ich erkennen kann.
ServeHTTP
zugreifen kann es auch. Beachten Sie, dass wir unsere Handler nicht als Methoden für appHandler
, d. h. func (ah *appHandler) IndexHandler(...)
definieren können, da wir den Handler in ServeHTTP
(d. h. ah.h(w,r)
) aufrufen müssen.
Dies ist auch, am wichtigsten, vollständig kompatibel mit http.Handler
, so dass wir unsere Handler-Struktur immer noch mit generischer Middleware umschließen können: gzipHandler(appHandler{context.IndexHandler, context})
.
(Ich bin immer noch offen für andere Vorschläge!)
Aktualisieren
Dank dieser großartigen Antwort auf Reddit konnte ich eine bessere Lösung finden das erforderte nicht, zwei Referenzen auf meine context
Instanz pro Anfrage zu übergeben.
Stattdessen erstellen wir nur eine Struktur, die einen eingebetteten Kontext und unseren Handler-Typ akzeptiert, und wir erfüllen trotzdem die http.Handler
-Schnittstelle dank ServeHTTP
. Handler sind keine Methoden mehr auf unserem appContext
-Typ, sondern akzeptieren sie einfach als Parameter, was zu einer etwas längeren Funktionssignatur führt, aber dennoch "offensichtlich" und einfach zu lesen ist. Wenn wir uns Gedanken über das "Tippen" machen, brechen wir sogar, weil wir keinen Empfänger mehr haben, um den wir uns kümmern müssen.
Tags und Links go