गो

2013-01-16 13 views
7

के साथ सामान्य ऐप इंजन हैंडलर कार्यों को पूरा करना यह एक सर्वोत्तम अभ्यास प्रश्न है जिसका शायद एक सही उत्तर नहीं है। ऐसा लगता है कि हैंडलर के लिए विशिष्ट कार्य शुरू करने से पहले मेरे अधिकांश हैंडलर को कई सामान्य प्रारंभिक नौकरियों को करने की आवश्यकता है। उदाहरण उपयोगकर्ता लेख होंगे, लोकेल का पता लगाएंगे और अनुवादित तारों को लोड करेंगे, memcached मानों की जांच करेंगे, और इसी तरह।गो

init के भीतर इन कार्यों में से कुछ का ख्याल रखना उचित लगेगा, लेकिन अधिकांश को Http.Request या appengine.Context की आवश्यकता होती है।

  1. लागू ServeHTTP और अंत में एक कस्टम init समारोह निष्पादित करने की क्षमता जोड़ने: जहाँ तक मैं देख सकता हूँ यह तीन विकल्प छोड़ देता है। समस्या यह है कि, मैं गोरिल्ला मक्स का उपयोग नहीं कर पाऊंगा जो अपने ServeHTTP लागू करता है।

  2. मक्स (आदर्श से कम) का एक फोर्क संस्करण का उपयोग करें।

  3. ऐप में प्रत्येक हैंडलर की शुरुआत में 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. 

उत्तर

8

आप एक (समारोह) बना सकते हैं टाइप जो एक ServeHTTP है कि सब कुछ आप की जरूरत करता है, और उसके बाद आंतरिक रूप से मूल फ़ंक्शन को कॉल करने, और फिर अपने संचालकों कन्वर्ट

package main 

import (
     "fmt" 
     "log" 
     "net/http" 
) 

type wrappedHandler func(w http.ResponseWriter, r *http.Request) 

func (h wrappedHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 
     log.Println("Do Other GAE Stuff") 
     h(w, r) 
} 

func handler(w http.ResponseWriter, r *http.Request) { 
     fmt.Fprintf(w, "Hi!") 
} 

func main() { 
     http.Handle("/", wrappedHandler(handler)) 
     http.ListenAndServe(":8080", nil) 
} 

आप handler() समारोह में कुछ पास करना चाहते हैं, तो आप इसे हस्ताक्षर जैसे को जोड़ सकते हैं: उस प्रकार के

type wrappedHandler func(w http.ResponseWriter, r *http.Request, conn *db.Connection) 

func (h wrappedHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 
     conn := db.CreateConnection(); 
     h(w, r, conn) 
} 


func handler(w http.ResponseWriter, r *http.Request, conn *db.Connection) { 
     data := conn.AllTheData() 
     fmt.Fprintf(w, data) 
} 
+1

मैं शुरू में सोचा था कि मैं गोरिल्ला मक्स का इस तरह से उपयोग नहीं कर सका, तो मैंने कास्ट देखा! अच्छा लगा। यह ट्यूटोरियल कुछ और नमूना कोड प्रदान करता है: http://shadynasty.biz/blog/2012/08/07/painless-web-handlers-in-go/। मैं जीएई-विशिष्ट उदाहरण के साथ पहली पोस्ट संपादित करूंगा। धन्यवाद :) –

+1

बढ़िया! यह आपके दिमाग को पहले चारों ओर लपेटने के लिए एक छोटी सी चीज है (एक func में कोई फ़ंक्शन है?) लेकिन यह बहुत शक्तिशाली है! मुझे लगता है कि ब्लॉग पोस्ट वह जगह है जहां मैंने इसे पहले भी सीखा था। अच्छी श्रृंखला – minikomi

+1

मुझे यह समझने में परेशानी थी कि आप प्रभावी रूप से श्रृंखला में दो ServeHTTP कर सकते हैं: पहले मक्स का एक, फिर अपना खुद का। प्रश्न नमूना ऐप इंजन ऐप के साथ अपडेट किया गया। –