为了账号安全,请及时绑定邮箱和手机立即绑定

如何正确地将控制器设置为 Golang 中的路由?

如何正确地将控制器设置为 Golang 中的路由?

Go
米脂 2023-06-12 14:19:01
我是Golang的新手,需要一些帮助。我正在尝试创建没有 ORM 的 REST API Web 服务。现在我已成功连接到PostgreSQL数据库。在数据库中,我有一个名为factors. 我想创建 CRUD 操作。问题出在控制器逻辑上。主要去:package mainimport (    "github.com/gorilla/mux"    "log"    "net/http"    "rest_api/configurations"    "rest_api/controllers")func main()  {    db, err := configurations.PostgreSQLDatabase()    if err != nil {        log.Fatal(err)    }    router := mux.NewRouter()    router.StrictSlash(true)    subrouter := router.PathPrefix("/api").Subrouter()    subrouter.HandleFunc("/factors", controllers.GetFactors(db)).Methods("GET")    log.Fatal(http.ListenAndServe(":8000", router))}模型/factors.go:package modelstype Factor struct {    ID int `json:"id"`    Name string `json:"name"`}控制器看起来有多正确GetFactors?有人可以告诉我吗?例如,我将db对象传递给GetFactors控制器,如下例所示。不幸的是,它似乎是不正确的。控制器/factors.go:func GetFactors(db *sql.DB, w http.ResponseWriter, req *http.Request) {    // some code}配置/PostgreSQL.go :func PostgreSQLDatabase() (*sql.DB, error) {    // Load environment variables from ".env" file.    err := godotenv.Load(".env")    if err != nil {        log.Fatal(err)    }    // Initialize database-related variables.    dbUser := os.Getenv("PostgreSQL_USER")    dbPassword := os.Getenv("PostgreSQL_PASSWORD")    dbHost := os.Getenv("PostgreSQL_HOST")    dbName := os.Getenv("PostgreSQL_DB_NAME")    dbURL := fmt.Sprintf("user=%s password=%s host=%s dbname=%s sslmode=disable", dbUser, dbPassword, dbHost, dbName)    // Create PostgreSQL database connection pool.    db, err := sql.Open("postgres", dbURL)    if err != nil {        return nil, err    }    // Ping PostgreSQL database to make sure it's alive.    err = db.Ping()    if err != nil {        log.Fatal(err)    } else {        log.Println("Web service successfully connected to remote PostgreSQL database.")    }    return db, nil}
查看完整描述

3 回答

?
慕标5832272

TA贡献1966条经验 获得超4个赞

我喜欢使用的一种模式是定义您自己的Router结构,该结构具有一个mux.Router字段,并封装诸如您的数据库连接、应用程序配置等内容。


我发现这样做可以在需要不同资源和开发收益时轻松更新您的路线。


首先创建一个路由器对象,它在创建时接收数据库连接,并使其可用于您希望使用的所有路由。


路由器.go


package main


import (

    "net/http"

    "database/sql"


    "github.com/gorilla/mux"

)


type Router struct {

    router *mux.Router

    db *sql.DB

}


func NewRouter(db *sql.DB) (*Router, error) {

    router := mux.NewRouter()

    router.StrictSlash(true)

    subrouter := router.PathPrefix("/api").Subrouter()


    r := &Router{

        router: router,

        db: db,

    }


    subrouter.HandleFunc("/factors", r.GetFactors).Methods(http.MethodGet)


    return r, nil

}


func (r *Router) GetFactors(w http.ResponseWriter, req *http.Request) {

    // Now you can access your database via `r.db`

}


// Needed so we can pass our custom router to ListenAndServe.

func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {

    r.router.ServeHTTP(w, req)

}

然后main.go你可以简单地创建你的自定义路由器,将它传递给你的数据库连接。然后自定义路由器可以直接传递给ListenAndServe.


主程序


package main


import (

    "log"

    "net/http"

    "rest_api/configurations"

    "rest_api/controllers"

)


func main()  {

    db, err := configurations.PostgreSQLDatabase()

    if err != nil {

        log.Fatal(err)

    }


    router, err := NewRouter(db)

    if err != nil {

        log.Fatalf("error initializing router: %v", err)

    }


    log.Fatal(http.ListenAndServe(":8000", router))

}

希望这会有所帮助。


查看完整回答
反对 回复 2023-06-12
?
梵蒂冈之花

TA贡献1900条经验 获得超5个赞

没有正确的方法,它主要基于意见。


HandlerFunc 函数的语义应该是这样的func(w http.ResponseWriter, r *http.Request),为了传递数据库,你可以使用闭包,这里是一个例子。


主程序

// ... some code here 

subrouter.HandleFunc("/factors", controllers.GetFactors(db)).Methods("GET")

// ... some code here

控制器/factors.go

func GetFactors(db *sql.DB) http.HandlerFunc {

  return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {

    // some code

  })

}

另外一个选择:


我不太确定这一点,但你可以根据你的需要调整它。初始化一个Controller结构并将数据库传递给它:


主程序

// ... some code here 

db, err := configurations.PostgreSQLDatabase()

if err != nil {

    log.Fatal(err)

}

ctrl := controllers.Controller{DB: db}

subrouter.HandleFunc("/factors", ctrl.GetFactors).Methods("GET")

// ... some code here

表示 Controller 结构上的方法。在控制器中定义一个结构


控制器/factors.go

type Controller struct {

  DB *PostgreSQLDatabase

}


func (c Controller) GetFactors(w http.ResponseWriter, req *http.Request) {

    // some code

    // c.DB.MySqlMethod()

}


查看完整回答
反对 回复 2023-06-12
?
牧羊人nacy

TA贡献1862条经验 获得超7个赞

您的功能GetFactors必须如下所示:


func GetFactors(w http.ResponseWriter, r *http.Request) {}

在主文件中你必须有:


subrouter.HandleFunc("/factors", controllers.GetFactors).Methods("GET")

为了获得数据库连接,你必须GetDB在你的包中有类似的功能"rest_api/configurations"。


在"rest_api/configurations"你必须有类似的东西:


var db *PostgreSQLDatabase


func init() {

    var err error

    db, err = configurations.PostgreSQLDatabase()

    if err != nil {

        log.Fatal(err)

    }

}


func GetDB() *PostgreSQLDatabase {

  return db

}


查看完整回答
反对 回复 2023-06-12
  • 3 回答
  • 0 关注
  • 101 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信