如何在Golang中将vars传递给chi路由器

I'm writing a web app using chi router and have global vars for the database connection string and gorilla sessions mysqlstore. I want to pass these to the chi mount function instead of using global vars but can't figure out how to do it.

Here is my code, redacted for brevity.

var dBSource string

var store *mysqlstore.MySQLStore

func main() {

  var err error

  dBSource = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8", dbUser, dbPass, dbHost, dbPort, dbName)

  store, err = mysqlstore.NewMySQLStore(endpoint, tableName, path, maxAge, codecs)

  defer store.Close()

  r := chi.NewRouter()

  r.Mount("/users", usersResource{}.Routes())
}

type usersResource struct{}

func (rs usersResource) Routes() chi.Router {
    r := chi.NewRouter()

    r.Get("/", rs.List)

    return r
}

func (rs usersResource) List(w http.ResponseWriter, r *http.Request) {

    session, err := store.Get(r, "session-data")

    db, err := sql.Open("mysql", dBSource)
}

Usually, we do that this way.


func main() {

......
  r := chi.NewRouter()

  // keep db connection alive.
  db, err := sql.Open("mysql", dBSource)

  ur := NewUserResource(store, db)

  r.Mount("/users", ur.Routes())
}

type usersResource struct{
  store *mysqlstore.MySQLStore
// and more...
  db *YourDB
}

// new function to pass global var
func newUserResource(store *mysqlstore.MySQLStore, db *YourDB) *usersResource{
  return &usersResource {
    store: store,
    db: db,
  }
}

func (rs *usersResource) List(w http.ResponseWriter, r *http.Request) {
    // don't use global var
    session, err := ur.store.Get(r, "session-data")

    ur.db.GetWhatever()

}

For completeness, here is how I implemented the accepted solution. Hopefully, it may save another newbie a bunch of time.

type appResource struct {
    tmpl  *template.Template // net/http
    store *mysqlstore.MySQLStore
    db    *sql.DB // database/sql
}

func newAppResource(store *mysqlstore.MySQLStore, db *sql.DB, tmpl *template.Template) *appResource {
    return &appResource{
        tmpl:  tmpl,
        store: store,
        db:    db,
    }
}

func main() {

  var err error

  err = godotenv.Load()
  if err != nil {
     log.Fatal("Error loading .env file")
  }

  dbUser := os.Getenv("dbUser")
  dbName := os.Getenv("dbName")
  dbPass := os.Getenv("dbPass")
  dbHost := os.Getenv("dbHost")
  dbPort := os.Getenv("dbPort")

  dBSource := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8", dbUser, dbPass, dbHost, dbPort, dbName)

  db, err := sql.Open("mysql", dBSource)
  if err != nil {
     log.Fatal(err)
  }

  sessionKey := os.Getenv("sessionKey")

  endpoint := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?parseTime=true&loc=Local", dbUser, dbPass, dbHost, dbPort, dbName)
  tableName := "sessions"
  path := "/"
  maxAge := 3600
  codecs := []byte(sessionKey)

  store, err := mysqlstore.NewMySQLStore(endpoint, tableName, path, maxAge, codecs)
  if err != nil {
    log.Println("SESSIONS STORE error")
    log.Fatal(err)
  }

  r := chi.NewRouter()

  r.Get("/", rs.adminIndex)

  r.Mount("/users", rs.userRoutes())

  httpPort := os.Getenv("httpPort")

  http.ListenAndServe(httpPort, r)
}

func (rs *appResource) adminIndex(w http.ResponseWriter, r *http.Request) {
    session, err := rs.store.Get(r, "admin-data")
    if err != nil {
        log.Fatal(err)
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    var flash map[string]interface{}

    if flashes := session.Flashes(); len(flashes) > 0 {
        v := map[string]interface{}{
            "FlashedMessages": session.Flashes(),
        }
        flash = v
    }

    if err := rs.tmpl.ExecuteTemplate(w, "admin-index", flash); err != nil {
        log.Println(err.Error())
        http.Error(w, http.StatusText(500), 500)
    }
}