के साथ सामान्य ऐप इंजन हैंडलर कार्यों को पूरा करना यह एक सर्वोत्तम अभ्यास प्रश्न है जिसका शायद एक सही उत्तर नहीं है। ऐसा लगता है कि हैंडलर के लिए विशिष्ट कार्य शुरू करने से पहले मेरे अधिकांश हैंडलर को कई सामान्य प्रारंभिक नौकरियों को करने की आवश्यकता है। उदाहरण उपयोगकर्ता लेख होंगे, लोकेल का पता लगाएंगे और अनुवादित तारों को लोड करेंगे, memcached मानों की जांच करेंगे, और इसी तरह।गो
init
के भीतर इन कार्यों में से कुछ का ख्याल रखना उचित लगेगा, लेकिन अधिकांश को Http.Request
या appengine.Context
की आवश्यकता होती है।
लागू
ServeHTTP
और अंत में एक कस्टम init समारोह निष्पादित करने की क्षमता जोड़ने: जहाँ तक मैं देख सकता हूँ यह तीन विकल्प छोड़ देता है। समस्या यह है कि, मैं गोरिल्ला मक्स का उपयोग नहीं कर पाऊंगा जो अपनेServeHTTP
लागू करता है।मक्स (आदर्श से कम) का एक फोर्क संस्करण का उपयोग करें।
ऐप में प्रत्येक हैंडलर की शुरुआत में
startHandler
फ़ंक्शन डालें। बोझिल लगता है, हालांकि मुझे लगता है कि यहServeHTTP
में 'छिपाने' सामान्य कोड के विरोध में क्या हो रहा है, यह बिल्कुल स्पष्ट करता है।
सभी हैंडलरों के लिए सामान्य नौकरियों की देखभाल करने का पसंदीदा तरीका क्या है? क्या मुझे एक और दृष्टिकोण याद आ रहा है?
मिनीकोमी के उत्तर में उल्लिखित दृष्टिकोण का एक पूर्ण ऐप इंजन उदाहरण यहां दिया गया है। यह Jeff Wendling's tutorial पर जाने के लायक भी है।
package app
import (
"fmt"
"log"
"net/http"
"appengine"
"appengine/datastore"
"github.com/gorilla/context"
"github.com/gorilla/mux"
)
type Config struct {
DefaultLocale string
DefaultTimezone string
}
type ContextKey int
const (
SiteConfig ContextKey = iota
// ...
)
type InitHandler func(http.ResponseWriter, *http.Request, appengine.Context)
func (h InitHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// All handler initialisation tasks go here
c := appengine.NewContext(r)
k := datastore.NewKey(c, "Config", "site:config", 0, nil)
config := new(Config)
if err := datastore.Get(c, k, config); err != nil {
log.Fatal("Couldn't read config from datastore: %s\n", err.Error())
}
context.Set(r, SiteConfig, config)
// Finally, call the handler itself
h(w, r, c)
}
func init() {
r := mux.NewRouter()
r.Handle("/", InitHandler(home)) // Note: NOT r.HandleFunc!
http.Handle("/", r)
}
func home(w http.ResponseWriter, r *http.Request, c appengine.Context) {
site := context.Get(r, SiteConfig).(*Config)
fmt.Fprintf(w, "Locale: %s, timezone: %s.", site.DefaultLocale, site.DefaultTimezone)
}
क्या मुझे थोड़ी देर के लिए फेंक दिया router.Handle
और नहीं router.HandleFunc
उपयोग करने की आवश्यकता है। डेटासंग्रह में एक उपयुक्त इकाई मानते हुए, उत्पादन लगता है:
Locale: en_US, timezone: UTC.
मैं शुरू में सोचा था कि मैं गोरिल्ला मक्स का इस तरह से उपयोग नहीं कर सका, तो मैंने कास्ट देखा! अच्छा लगा। यह ट्यूटोरियल कुछ और नमूना कोड प्रदान करता है: http://shadynasty.biz/blog/2012/08/07/painless-web-handlers-in-go/। मैं जीएई-विशिष्ट उदाहरण के साथ पहली पोस्ट संपादित करूंगा। धन्यवाद :) –
बढ़िया! यह आपके दिमाग को पहले चारों ओर लपेटने के लिए एक छोटी सी चीज है (एक func में कोई फ़ंक्शन है?) लेकिन यह बहुत शक्तिशाली है! मुझे लगता है कि ब्लॉग पोस्ट वह जगह है जहां मैंने इसे पहले भी सीखा था। अच्छी श्रृंखला – minikomi
मुझे यह समझने में परेशानी थी कि आप प्रभावी रूप से श्रृंखला में दो ServeHTTP कर सकते हैं: पहले मक्स का एक, फिर अपना खुद का। प्रश्न नमूना ऐप इंजन ऐप के साथ अपडेट किया गया। –