Using method values to get rid of global variables
Have you ever had a piece of Go code like this:
// TODO: Get rid of this global variable.
var foo service
func fooHandler(w http.ResponseWriter, req *http.Request) {
// code that uses foo
}
func main() {
foo = initFoo()
http.HandleFunc("/foo", fooHandler)
}
One way to get rid of that global variable is to use method values:
type fooHandler struct {
foo service
}
func (h fooHandler) Handle(w http.ResponseWriter, req *http.Request) {
// code that uses h.foo
}
func main() {
foo := initFoo()
http.HandleFunc("/foo", fooHandler{foo: foo}.Handle)
}
Of course, net/http
also has http.Handle
so in this case you can simply change fooHandler
to implement http.Handler
interface:
type fooHandler struct {
foo service
}
func (h fooHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// code that uses h.foo
}
func main() {
foo := initFoo()
http.Handle("/foo", fooHandler{foo: foo})
}
But method values are great when you need to provide a func
, for example in https://godoc.org/path/filepath#Walk or https://godoc.org/net/http#Server.ConnState.
If you have two or more global dependencies, would you put them in the same struct? I guess at this point it becomes a "context"...
Also, does this closure approach look simpler to you?