dryb38654 2019-02-25 13:54
浏览 52
已采纳

如何正确使控制器指向Golang中的路由?

I am new in Golang and need some help. I am tring to create REST API web service without ORM.

Right now I am successfully connected to PostgreSQL database. In database I have table which called factors. I want to create CRUD operations. The problem is with controllers logic.

main.go:

package main

import (
    "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))
}

models/factors.go:

package models

type Factor struct {
    ID int `json:"id"`
    Name string `json:"name"`
}

How correctly looks like the GetFactors controller? Can someone show me please. For instance I pass db object to GetFactors controller as in the example below. Unfortunately it seems like it's incorrect.

controllers/factors.go:

func GetFactors(db *sql.DB, w http.ResponseWriter, req *http.Request) {
    // some code
}

configurations/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条回答 默认 最新

  • dongmi4035 2019-02-25 18:03
    关注

    A pattern I like to use is to define your own Router struct that has a mux.Router as a field as well as encapsulates things like your database connection, application config and etc.

    I find doing it this way makes it easily update your routes when they require different resources and development proceeds.

    First create a router object that takes in the database connection on creation and makes it available to all routes you wish to use.

    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)
    }
    

    Then in main.go you can simply create your custom router, passing it your database connection. Then the custom router can be passed directly to ListenAndServe.

    main.go

    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))
    }
    

    Hopefully this helps.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 file converter 转换格式失败 报错 Error marking filters as finished,如何解决?
  • ¥15 ubuntu系统下挂载磁盘上执行./提示权限不够
  • ¥15 Arcgis相交分析无法绘制一个或多个图形
  • ¥15 关于#r语言#的问题:差异分析前数据准备,报错Error in data[, sampleName1] : subscript out of bounds请问怎么解决呀以下是全部代码:
  • ¥15 seatunnel-web使用SQL组件时候后台报错,无法找到表格
  • ¥15 fpga自动售货机数码管(相关搜索:数字时钟)
  • ¥15 用前端向数据库插入数据,通过debug发现数据能走到后端,但是放行之后就会提示错误
  • ¥30 3天&7天&&15天&销量如何统计同一行
  • ¥30 帮我写一段可以读取LD2450数据并计算距离的Arduino代码
  • ¥15 飞机曲面部件如机翼,壁板等具体的孔位模型