Mysql Golang将参数传递给gorilla路由器

Mysql Golang将参数传递给gorilla路由器,mysql,go,Mysql,Go,所以我有两个文件。在其中一个中,我初始化了一个gorilla路由器,并注册了处理程序。在另一个示例中,我定义了处理程序。处理程序应该查询MYSQL数据库。走吧,看起来像这样- package main import ( "net/http" "github.com/gorilla/mux" "database/sql" _ "github.com/go-sql-driver/mysql" "fmt" ) type Route struct {

所以我有两个文件。在其中一个中,我初始化了一个gorilla路由器,并注册了处理程序。在另一个示例中,我定义了处理程序。处理程序应该查询MYSQL数据库。走吧,看起来像这样-

    package main

import (
    "net/http"
    "github.com/gorilla/mux"
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
    "fmt"
)

type Route struct {
    Name string
    Method string
    Pattern string
    HandlerFunc http.HandlerFunc
}

type Routes[]Route

func NewRouter() *mux.Router {
    db, err := sql.Open("mysql", "psanker:123@/education_data")
    err = db.Ping()

    if err != nil {
        fmt.Println("Failed to prepare connection to database")
        log.Fatal("Error:", err.Error())
    }

    defer db.Close()

    router := mux.NewRouter().StrictSlash(true)
    for _, route := range routes {
        router.
            Methods(route.Method).
            Path(route.Pattern).
            Name(route.Name).
            Handler(route.HandlerFunc)
    }
    return router
}

var routes = Routes{
    Route {
        "Index",
        "GET",
        "/",
        Index,
    },
    Route {
        "getDistrict",
        "GET",
        "/district/{districtId}",
        getDistrict,
        DBConn &db,
    },
    Route {
        "getDistricts",
        "GET",
        "/districts",
        getDistricts,
    },
}
我的handlers.go文件如下所示-

package main

import (
    "fmt"
    "net/http"
    "github.com/gorilla/mux"
    "encoding/json"
)

func Index(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "WELCOME!")
}

func getDistrict(w http.ResponseWriter, r *http.Request) {
    vars := mux.Vars(r)
    districtId := vars["districtId"]
    fmt.Fprintln(w, "District id : ", districtId)
}

func getDistricts(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json;charset=UTF-8")
    w.WriteHeader(http.StatusOK)
    rows, err := db.Query("SELECT * from districts")
    check(err)
    var district District
    for rows.Next() {
        var id int64
        test := "hey"
        district = District{Id: id, Activities: test}
    }

    if err := json.NewEncoder(w).Encode(district); err != nil {
        check(err)
    }
}

我想为所有处理程序使用一个数据库连接,如何实现这一点?

Go的
sql.DB
类型表示一个连接池,而不是单个连接。建议您在程序初始化时创建一个池,并且:

  • 创建一个全局池并使用它(该池对于并发访问是安全的)

  • 创建满足http.handler的自定义处理程序函数,并接受池或包含池的结构作为附加参数。我在这里写到:

  • (我想提供另一个例子,但我在移动电话上;请原谅我的错误)


    另外,请查看如何简化从结构处理到结构处理的查询

    Elithar的答案是实现这一目标的标准方法。如果您想在每个处理程序中注入一个db连接,这是一种解决方法。您可以定义自己的处理程序,并将其转换回路由器期望的处理程序。我想这就是Elithar想要给出的例子

    func main() {
        http.HandlerFunc(myDbHandler(Index, db))
    }
    
    type dbHandler func(w http.ResponseWriter, r *http.Request, db *sql.DB)
    
    func myDbHandler(handler dbHandler, db *sql.DB) func(w http.ResponseWriter, r *http.Request) {
        return func(w http.ResponseWriter, r *http.Request) {
            handler(w, r, db)
        }
    }
    
    func Index(w http.ResponseWriter, r *http.Request, db *sql.DB) {
        // handler code goes here
    }
    

    嗨,我想回答你的问题,但是你的代码现在有一些问题,这让我不确定如何做。如果您可以保持此连接打开,那么您真正想要的就是将其定义为您的主包,并在打开路由之前进行设置。无论如何,在
    routes
    的复合文字声明中,您使用
    db
    ,即使它不在范围内,并且(即使它在范围内)在
    Route
    实例中没有可分配给它的字段。如果你纠正的足够让我理解你的意图,那么我就可以更容易地提出一个解决方案。
    func main() {
        http.HandlerFunc(myDbHandler(Index, db))
    }
    
    type dbHandler func(w http.ResponseWriter, r *http.Request, db *sql.DB)
    
    func myDbHandler(handler dbHandler, db *sql.DB) func(w http.ResponseWriter, r *http.Request) {
        return func(w http.ResponseWriter, r *http.Request) {
            handler(w, r, db)
        }
    }
    
    func Index(w http.ResponseWriter, r *http.Request, db *sql.DB) {
        // handler code goes here
    }