32

Gin ( https://gin-gonic.github.io/gin/ ) を使用して、Golang で単純な RESTful JSON API を構築しています。

ルートは次のように設定されます。

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

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

私の質問は、引数を testRouteHandler 関数に渡すにはどうすればよいですか? たとえば、共通のデータベース接続は、ルート間で再利用したいものになる可能性があります。

これをグローバル変数に入れる最良の方法はありますか? または、Go で追加の変数を testRouteHandler 関数に渡す方法はありますか? Goの関数にはオプションの引数がありますか?

PS。私はGoの学習を始めたばかりなので、私が見逃していることは明らかです:)

4

7 に答える 7

42

「アプリケーション スコープ」の依存関係 (DB 接続プールなど) をリクエスト コンテキストに詰め込むことは避けます。あなたの2つの「最も簡単な」オプションは次のとおりです。

  1. グローバルにします。これは小規模なプロジェクトでは問題なく、*sql.DBスレッドセーフです。
  2. 戻り値の型が満たされるように、クロージャで明示的に渡しますgin.HandlerFunc

例えば

// 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")
}
于 2015-12-03T02:20:31.027 に答える
33

コメントに投稿したリンクを使用して、簡単な例を作成しました。

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

これは単なる POC です。しかし、私はそれが始まりだと信じています。それが役に立てば幸い。

于 2015-12-02T21:11:29.747 に答える