title: Passing Context to Interface Methods
body: <p>Somewhat inspired by <a href="https://medium.com/@benbjohnson/structuring-applications-in-go-3b04be4ff091">this article</a> last week, I'm toying with refactoring an application I have to more explicitly pass context (DB pools, session stores, etc) to my handlers.</p>
  
  <p>However, one issue I'm having is that without a global templates map, the <code>ServeHTTP</code> method on my custom handler type (as to satisfy <code>http.Handler</code>) can no longer access the map to render a template.</p>
  
  <p>I need to either retain the global <code>templates</code> variable, or re-define my custom handler type as a struct. </p>
  
  <p>Is there a better way to achieve this?</p>
  
  <p><strong>func.go</strong></p>
  
  <pre><code>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"
  )
  
  var templates map[string]*template.Template
  
  type appContext struct {
      db    *sqlx.DB
      store *sessions.CookieStore
  }
  
  type appHandler func(w http.ResponseWriter, r *http.Request) (int, error)
  
  func (ah appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
      // templates must be global for us to use it here
      status, err := ah(w, r)
      if err != nil {
          log.Printf("HTTP %d: %q", status, err)
          switch status {
          case http.StatusNotFound:
              // Would actually render a "http_404.tmpl" here...
              http.NotFound(w, r)
          case http.StatusInternalServerError:
              // Would actually render a "http_500.tmpl" here
              // (as above)
              http.Error(w, http.StatusText(status), status)
          default:
              // Would actually render a "http_error.tmpl" here
              // (as above)
              http.Error(w, http.StatusText(status), status)
          }
      }
  }
  
  func main() {
      // Both are 'nil' just for this example
      context := &amp;appContext{db: nil, store: nil}
  
      r := web.New()
      r.Get("/", appHandler(context.IndexHandler))
      graceful.ListenAndServe(":8000", r)
  }
  
  func (app *appContext) IndexHandler(w http.ResponseWriter, r *http.Request) (int, error) {
      fmt.Fprintf(w, "db is %q and store is %q", app.db, app.store)
      return 200, nil
  }
  </code></pre>
  
  <p><strong>struct.go</strong></p>
  
  <pre><code>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"
  )
  
  type appContext struct {
      db        *sqlx.DB
      store     *sessions.CookieStore
      templates map[string]*template.Template
  }
  
  // We need to define our custom handler type as a struct
  type appHandler struct {
      handler func(w http.ResponseWriter, r *http.Request) (int, error)
      c       *appContext
  }
  
  func (ah appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
      status, err := ah.handler(w, r)
      if err != nil {
          log.Printf("HTTP %d: %q", status, err)
          switch status {
          case http.StatusNotFound:
              // Would actually render a "http_404.tmpl" here...
              http.NotFound(w, r)
          case http.StatusInternalServerError:
              // Would actually render a "http_500.tmpl" here
              // (as above)
              http.Error(w, http.StatusText(status), status)
          default:
              // Would actually render a "http_error.tmpl" here
              // (as above)
              http.Error(w, http.StatusText(status), status)
          }
      }
  }
  
  func main() {
      // Both are 'nil' just for this example
      context := &amp;appContext{db: nil, store: nil}
  
      r := web.New()
      // A little ugly, but it works.
      r.Get("/", appHandler{context.IndexHandler, context})
      graceful.ListenAndServe(":8000", r)
  }
  
  func (app *appContext) IndexHandler(w http.ResponseWriter, r *http.Request) (int, error) {
      fmt.Fprintf(w, "db is %q and store is %q", app.db, app.store)
      return 200, nil
  }
  </code></pre>
  
  <p>Is there a cleaner way to pass the <code>context</code> instance to <code>ServeHTTP</code>?</p>
  
  <p>Note that <code>go build -gcflags=-m</code> shows that neither option appears to be worse in teams of heap allocation: the <code>&amp;appContext</code> literal escapes to the heap (as expected) in both cases, although my interpretation is that the struct-based option does pass a second pointer (to <code>context</code>) on each request—<strong>correct me if I'm wrong here</strong> as I'd love to get a better understanding of this.</p>
  
  <p>I'm not wholly convinced that globals are bad in package main (i.e. not a lib) provided they are safe to use in that manner (read only/mutexes/a pool), but I do like clarity having to explicitly pass context provides.</p>