2015-12-02 13 views
13

Tôi đang sử dụng Gin, https://gin-gonic.github.io/gin/, để xây dựng một API JSON RESTful đơn giản với Golang.Làm thế nào để chuyển đối số cho bộ xử lý bộ định tuyến trong Golang bằng cách sử dụng khung web Gin?

Các tuyến đường được thiết lập với một cái gì đó như thế này:

func testRouteHandler(c *gin.Context) { 
    // do smth 
} 

func main() { 
    router := gin.Default() 
    router.GET("/test", testRouteHandler) 
    router.Run(":8080") 
} 

Câu hỏi của tôi là làm thế nào tôi có thể vượt qua xuống một cuộc tranh cãi với chức năng testRouteHandler? Ví dụ một kết nối cơ sở dữ liệu phổ biến có thể là một cái gì đó mà một người muốn sử dụng lại giữa các tuyến đường.

Cách tốt nhất để có điều này trong một biến toàn cầu? Hoặc là có một số cách trong Go để vượt qua cùng một biến thêm vào chức năng testRouteHandler? Có các đối số tùy chọn cho các hàm trong Go không?

PS. Tôi chỉ mới bắt đầu học Go, vì vậy có thể có điều gì đó hiển nhiên là tôi bị thiếu :)

+2

Tôi nghĩ rằng bạn đang tìm kiếm một trung HTTP Đây là một nơi tốt để bắt đầu https://www.nicolasmerouze.com/middlewares-golang -best-practices-examples/ – MIkCode

+0

Như @MIkCode đã nói, phần giữa là cách để đi ... hãy xem các phần mềm tùy chỉnh của Gin. https://github.com/gin-gonic/gin#custom-middleware – rcmgleite

Trả lời

13

Sử dụng liên kết tôi đăng trên nhận xét, tôi đã tạo một ví dụ đơn giản.

package main 

import (
    "log" 

    "github.com/gin-gonic/gin" 
    "github.com/jinzhu/gorm" 
    _ "github.com/mattn/go-sqlite3" 
) 

// ApiMiddleware will add the db connection to the context 
func ApiMiddleware(db gorm.DB) gin.HandlerFunc { 
    return func(c *gin.Context) { 
     c.Set("databaseConn", db) 
     c.Next() 
    } 
} 

func main() { 
    r := gin.New() 

    // In this example, I'll open the db connection here... 
    // In your code you would probably do it somewhere else 
    db, err := gorm.Open("sqlite3", "./example.db") 
    if err != nil { 
     log.Fatal(err) 
    } 

    r.Use(ApiMiddleware(db)) 

    r.GET("/api", func(c *gin.Context) { 
     // Don't forget type assertion when getting the connection from context. 
     dbConn, ok := c.MustGet("databaseConn").(gorm.DB) 
     if !ok { 
      // handle error here... 
     } 

     // do your thing here... 
    }) 

    r.Run(":8080") 
} 

Đây chỉ là POC đơn giản. Nhưng tôi tin rằng đó là một sự khởi đầu. Hy vọng điều đó sẽ hữu ích.

6

Tôi sẽ tránh việc phụ thuộc vào các ứng dụng 'phạm vi ứng dụng' (ví dụ: nhóm kết nối DB) vào ngữ cảnh yêu cầu. Hai tùy chọn 'dễ nhất' của bạn là:

  1. Biến nó thành toàn cầu. Điều này phù hợp với các dự án nhỏ hơn và *sql.DB là an toàn chỉ.
  2. Vượt qua nó một cách rõ ràng trong một đóng cửa để các kiểu trả về đáp ứng gin.HandlerFunc

ví dụ

// SomeHandler returns a `func(*gin.Context)` to satisfy Gin's router methods 
// db could turn into an 'Env' struct that encapsulates all of your 
// app dependencies - e.g. DB, logger, env vars, etc. 
func SomeHandler(db *sql.DB) gin.HandlerFunc { 
    fn := func(c *gin.Context) { 
     // Your handler code goes in here - e.g. 
     rows, err := db.Query(...) 

     c.String(200, results) 
    } 

    return gin.HandlerFunc(fn) 
} 

func main() { 
    db, err := sql.Open(...) 
    // handle the error 

    router := gin.Default() 
    router.GET("/test", SomeHandler(db)) 
    router.Run(":8080") 
} 
+0

Đây phải là câu trả lời được đề xuất. –

-1

Được rồi, tôi đã đưa cho bạn một ví dụ đơn giản. Nó sẽ hoạt động. Bạn có thể mở rộng nó theo nhu cầu

func main() { 
    router := gin.Default() 
    router.GET("/test/:id/:name", testRouteHandler) 
    router.Run(":8080") 
} 

func testRouteHandler(c *gin.Context) { 
    id := c.Params.ByName("id") 
    name := c.Params.ByName("name") 
} 

Bây giờ bạn sẽ phải gọi xử lý của bạn như sau http://localhost:8080/test/1/myname

1

trễ đến bên bạn, cho đến nay đây là đề nghị của tôi. phương pháp Incapsulate vào đối tượng với tin vars/công cộng trong đó:

package main 

import (
    "log" 

    "github.com/gin-gonic/gin" 
    "github.com/jinzhu/gorm" 
    _ "github.com/mattn/go-sqlite3" 
) 

type HandlerA struct { 
    Db gorm.DB 
} 

func (this *HandlerA) Get(c *gin.Context) { 

    log.Info("[%#f]", this.Db) 
    // do your thing here... 
} 

func main() { 
    r := gin.New() 

    // Init, should be separate, but it's ok for this sample: 
    db, err := gorm.Open("sqlite3", "./example.db") 
    if err != nil { 
     log.Fatal(err) 
    } 

    Obj := new(HandlerA) 
    Obj.Db = db // Or init inside Object 

    r := gin.New() 

    Group := r.Group("api/v1/") 
    { 
     Group.GET("/storage", Obj.Get) 
    } 

    r.Run(":8080") 
} 
Các vấn đề liên quan