This repository has been archived by the owner on Dec 27, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhandlermethods.go
105 lines (89 loc) · 2.95 KB
/
handlermethods.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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package main
import (
"fmt"
"html/template"
"math/rand"
"net/http"
"sync"
)
// ---
// handlers as server methods &
// handler-specific setup
// Route handlers as methods on server give access to server's dependencies.
// The downside is that sharing of common dependencies can lead to data races.
// handleSomething decorator returns a HandlerFunc closure to allow
// handler-specific setup
func (s *server) handleSomething() http.HandlerFunc {
thing := prepareThing()
return func(w http.ResponseWriter, r *http.Request) {
thing() // use thing in HandlerFunc
}
}
// name handlers to play nicely with alphabetical docs & autocomplete:
func (s *server) handleTasksCreate() (h http.HandlerFunc) { return h }
func (s *server) handleTasksDone() (h http.HandlerFunc) { return h }
func (s *server) handleTasksGet() (h http.HandlerFunc) { return h }
func (s *server) handleAuthLogin() (h http.HandlerFunc) { return h }
func (s *server) handleAuthLogout() (h http.HandlerFunc) { return h }
// ---
// handler method arguments
// arguments for handler-specific dependencies:
func (s *server) handleGreeting(format string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, format, r.FormValue("name"))
}
}
func (s *server) examplePassingFormats() {
// router.HandleFunc likely from https://github.com/gorilla/mux#examples
s.router.HandleFunc("/one", s.handleGreeting("Hello %s"))
s.router.HandleFunc("/two", s.handleGreeting("Hola %s"))
// ^ formats provided as arguments
}
// more examples of handler methods with arguments
func handleTemplate(template *template.Template) (h http.HandlerFunc) { return h }
func handleRandomQuote(q Quoter, r *rand.Rand) (h http.HandlerFunc) { return h }
func handleSendMagicLinkEmail(e EmailSender) (h http.HandlerFunc) { return h }
// ---
// inner types
func (s *server) handleGreet() (h http.HandlerFunc) {
// declaring types inside functions:
// * tells devs that these are function-only types
// * declutters package space
// * does not require long unique names for types
type request struct {
Name string
}
type response struct {
Greeting string `json:"greeting"`
}
// ... more stuff
return h
}
// ---
// lazy setup with sync.Once
func (s *server) handleTemplate(files ...string) http.HandlerFunc {
var (
init sync.Once
tpl *template.Template
tplerr error
)
return func(w http.ResponseWriter, r *http.Request) {
init.Do(func() {
// setup only happens the handler is first called
tpl, tplerr = template.ParseFiles(files...) // expensive
// if handler never called, parsing is never done (if done in
// handleTemplate, would definitely run once)
})
if tplerr != nil {
http.Error(w, tplerr.Error(), http.StatusInternalServerError)
return
}
tpl.Execute(w, "data") // use tpl
}
}
// ---
// ANCILLARY STUBS (to make compiler happy)
// some prep in a handler method
func prepareThing() (thing func()) { return thing }
// Quoter quotes.
type Quoter struct{}