GolangNote

Golang笔记

在go web 应用里避免全局变量

Permalink

下面是在go web 应用里避免全局变量的经验

Go: 避免直接使用全局变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package main

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

    "html/template"

    "github.com/gorilla/sessions"
    "github.com/jmoiron/sqlx"
    "github.com/zenazn/goji/graceful"
    "github.com/zenazn/goji/web"
)

// appContext contains our local context; our database pool, session store, template
// registry and anything else our handlers need to access. We'll create an instance of it
// in our main() function and then explicitly pass a reference to it for our handlers to access.
type appContext struct {
    db        *sqlx.DB
    store     *sessions.CookieStore
    templates map[string]*template.Template
    decoder *schema.Decoder
    // ... and the rest of our globals.
}

// We've turned our original appHandler into a struct with two fields:
// - A function type similar to our original handler type (but that now takes an *appContext)
// - An embedded field of type *appContext
type appHandler struct {
    *appContext
    H func(*appContext, http.ResponseWriter, *http.Request) (int, error)
}

// Our ServeHTTP method is mostly the same, and also has the ability to
// access our *appContext's fields (templates, loggers, etc.) as well.
func (ah appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    // Updated to pass ah.appContext as a parameter to our handler type.
    status, err := ah.H(ah.appContext, w, r)
    if err != nil {
        log.Printf("HTTP %d: %q", status, err)
        switch status {
        case http.StatusNotFound:
            http.NotFound(w, r)
            // And if we wanted a friendlier error page, we can
            // now leverage our context instance - e.g.
            // err := ah.renderTemplate(w, "http_404.tmpl", nil)
        case http.StatusInternalServerError:
            http.Error(w, http.StatusText(status), status)
        default:
            http.Error(w, http.StatusText(status), status)
        }
    }
}

func main() {
    // These are 'nil' for our example, but we'd either assign
    // the values as below or use a constructor function like
    // (NewAppContext(conf config) *appContext) that initialises
    // it for us based on our application's configuration file.
    context := &appContext{db: nil, store: nil} // Simplified for this example

    r := web.New()
    // We pass an instance to our context pointer, and our handler.
    r.Get("/", appHandler{context, IndexHandler})

    graceful.ListenAndServe(":8000", r)
}

func IndexHandler(a *appContext, w http.ResponseWriter, r *http.Request) (int, error) {
    // Our handlers now have access to the members of our context struct.
    // e.g. we can call methods on our DB type via err := a.db.GetPosts()
    fmt.Fprintf(w, "IndexHandler: db is %q and store is %q", a.db, a.store)
    return 200, nil
}

摘自《Custom Handlers and Avoiding Globals in Go Web Applications

本文网址: https://golangnote.com/topic/88.html 转摘请注明来源

Related articles

golang web 框架 goji 介绍

goji 是个后起的golang web框架,避免其它golang web 框架走过的坑,在性能、简单性方面做得很好。...

Golang Web 程序生产环境独立部署示例

一个 web 应用通常是跑在一个前端代理,如 Nginx 后,这样可以方便的在同一个服务器部署多个应用。这里说的独立部署是指让 go web 程序直接暴露在外面,独占 443、80 端口(俗称裸跑)。这样做除了性能有些提高外,更重要的是部署方便。...

golang Web框架综合比较

下面是Square工程师对当时几个流行的golang Web 框架比较,可作为选择web 框架参考。...

Write a Comment to "在go web 应用里避免全局变量"

Submit Comment Login
Based on Golang + fastHTTP + sdb | go1.18 Processed in 1ms