Ric*_*her 7 google-app-engine go
这是一个最佳实践问题,可能没有一个正确的答案.在开始特定于处理程序的工作之前,我的大多数处理程序似乎需要执行许多常见的初始化作业.示例包括用户身份验证,检测区域设置和加载已翻译的字符串,检查memcached值等.
在内部处理其中的一些任务似乎是合理的init,但大多数需要Http.Request或者appengine.Context.据我所知,这有三个选择:
实现ServeHTTP并添加在最后执行自定义init函数的功能.问题在于,我无法使用实现自己的Gorilla mux ServeHTTP.
使用分叉版本的mux(不太理想).
startHandler在整个应用程序的每个处理程序的开头放置一个函数.看起来很麻烦,虽然我认为它确切地说明了发生了什么,而不是"隐藏"常用代码ServeHTTP.
处理所有处理程序共同的工作的首选方法是什么?我错过了另一种方法吗?
这是minikomi答案中概述的方法的完整App Engine示例.参观Jeff Wendling的教程也很值得.
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)
}
Run Code Online (Sandbox Code Playgroud)
什么让我失望的是需要使用router.Handle而不是router.HandleFunc.假设数据存储区中有适当的实体,输出如下:
Locale: en_US, timezone: UTC.
Run Code Online (Sandbox Code Playgroud)
您可以创建一个(func)类型,它具有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)
}
Run Code Online (Sandbox Code Playgroud)
如果要将某些内容传递给handler()func,可以将其添加到签名中,例如:
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)
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1033 次 |
| 最近记录: |