मैं गोलांग के लिए बिल्कुल नया हूं और इस मूर्खतापूर्वक करने के लिए सबसे अच्छा तरीका काम करने की कोशिश कर रहा हूं।गोरिल्ला मक्स को संदर्भ पास करना - मुहावरे
मेरे पास मार्गों की एक सरणी है जो मैं स्थिर रूप से परिभाषित कर रहा हूं और gorilla/mux
पर जा रहा हूं। मैं प्रत्येक हैंडलर फ़ंक्शन को अनुरोध के समय और पैनिक्स को संभालने के साथ लपेट रहा हूं (मुख्य रूप से इसलिए मैं समझ सकता था कि रैपिंग कैसे काम करती है)।
मैं चाहता हूं कि वे प्रत्येक 'संदर्भ' तक पहुंच सकें - एक ऐसी संरचना जो एक-प्रति-http-server होने जा रही है, जिसमें डेटाबेस हैंडल, कॉन्फ़िगरेशन आदि जैसी चीज़ें हो सकती हैं। मैं क्या नहीं करता करना चाहते हैं एक स्थिर वैश्विक चर का उपयोग करें।
जिस तरह से मैं वर्तमान में इसे कर रहा हूं, मैं रैपर को संदर्भ संरचना तक पहुंच प्रदान कर सकता हूं, लेकिन मैं यह नहीं देख सकता कि इसे वास्तविक हैंडलर में कैसे प्राप्त किया जाए, क्योंकि यह http.HandlerFunc
होना चाहता है। मैंने सोचा था कि क्या मैं अपने ही का एक प्रकार है कि Context
के लिए एक रिसीवर था में http.HandlerFunc
परिवर्तित किया जाता है कर सकता है (और रैपर के लिए इसी तरह करते हैं, लेकिन (ज्यादा के बाद के बारे में खेल रहे हैं) मैं नहीं तो यह स्वीकार करने के लिए Handler()
मिल सकता है।
मैं मदद नहीं कर सकते लेकिन लगता है कि मैं यहाँ कुछ स्पष्ट याद कर रहा हूँ। नीचे कोड।
package main
import (
"fmt"
"github.com/gorilla/mux"
"html"
"log"
"net/http"
"time"
)
type Route struct {
Name string
Method string
Pattern string
HandlerFunc http.HandlerFunc
}
type Context struct {
route *Route
// imagine other stuff here, like database handles, config etc.
}
type Routes []Route
var routes = Routes{
Route{
"Index",
"GET",
"/",
index,
},
// imagine lots more routes here
}
func wrapLogger(inner http.Handler, context *Context) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
inner.ServeHTTP(w, r)
log.Printf(
"%s\t%s\t%s\t%s",
r.Method,
r.RequestURI,
context.route.Name,
time.Since(start),
)
})
}
func wrapPanic(inner http.Handler, context *Context) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func() {
if err := recover(); err != nil {
log.Printf("panic caught: %+v", err)
http.Error(w, http.StatusText(500), 500)
}
}()
inner.ServeHTTP(w, r)
})
}
func newRouter() *mux.Router {
router := mux.NewRouter().StrictSlash(true)
for _, route := range routes {
// the context object is created here
context := Context {
&route,
// imagine more stuff here
}
router.
Methods(route.Method).
Path(route.Pattern).
Name(route.Name).
Handler(wrapLogger(wrapPanic(route.HandlerFunc, &context), &context))
}
return router
}
func index(w http.ResponseWriter, r *http.Request) {
// I want this function to be able to have access to 'context'
fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
}
func main() {
fmt.Print("Starting\n");
router := newRouter()
log.Fatal(http.ListenAndServe("127.0.0.1:8080", router))
}
यहाँ है एक तरह से यह करने के लिए है, लेकिन यह बहुत भयानक लगती है। मैं मदद नहीं कर सकता लेकिन लगता है कि होना चाहिए ऐसा करने के लिए कुछ बेहतर तरीका हो सकता है - शायद उपclass (?) http.Handler
।
package main
import (
"fmt"
"github.com/gorilla/mux"
"html"
"log"
"net/http"
"time"
)
type Route struct {
Name string
Method string
Pattern string
HandlerFunc ContextHandlerFunc
}
type Context struct {
route *Route
secret string
}
type ContextHandlerFunc func(c *Context, w http.ResponseWriter, r *http.Request)
type Routes []Route
var routes = Routes{
Route{
"Index",
"GET",
"/",
index,
},
}
func wrapLogger(inner ContextHandlerFunc) ContextHandlerFunc {
return func(c *Context, w http.ResponseWriter, r *http.Request) {
start := time.Now()
inner(c, w, r)
log.Printf(
"%s\t%s\t%s\t%s",
r.Method,
r.RequestURI,
c.route.Name,
time.Since(start),
)
}
}
func wrapPanic(inner ContextHandlerFunc) ContextHandlerFunc {
return func(c *Context, w http.ResponseWriter, r *http.Request) {
defer func() {
if err := recover(); err != nil {
log.Printf("panic caught: %+v", err)
http.Error(w, http.StatusText(500), 500)
}
}()
inner(c, w, r)
}
}
func newRouter() *mux.Router {
router := mux.NewRouter().StrictSlash(true)
for _, route := range routes {
context := Context{
&route,
"test",
}
router.Methods(route.Method).
Path(route.Pattern).
Name(route.Name).
HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
wrapLogger(wrapPanic(route.HandlerFunc))(&context, w, r)
})
}
return router
}
func index(c *Context, w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, %q secret is %s\n", html.EscapeString(r.URL.Path), c.secret)
}
func main() {
fmt.Print("Starting\n")
router := newRouter()
log.Fatal(http.ListenAndServe("127.0.0.1:8080", router))
}
http://github.com/ पर एक नजर डालें एलेक्स्डवर्ड/स्टैक - यह मध्यवर्ती (हैंडलर) को ढेर करने के लिए एक आसान तरीका के साथ एक अच्छा सार प्रदान करता है श्रृंखला के माध्यम से एसएस संदर्भ। – Nadh
गोरिल्ला के पास एक संदर्भ पैकेज है। – freeformz
@ फ्रीफॉर्म गोरिल्ला का संदर्भ पैकेज प्रोग्राम संदर्भ के बजाय अनुरोध संदर्भ के लिए है। विशेष रूप से, यह अनुरोध के अंत में स्वचालित रूप से साफ़ हो जाता है (यदि आप गोरिल्ला/मक्स का उपयोग कर रहे हैं)। –