Go and Gin: Passing around struct for database context?

The values within context.Keys are all of type interface{}, so db will not be able to call methods from type *DB until it's converted back to that type.

The safe way:

db, ok := context.Keys["DB"].(*DB)
if !ok {
        //Handle case of no *DB instance
}
// db is now a *DB value

The less safe way, which will panic if context.Keys["DB"] is not a value of type *DB:

db := context.Keys["DB"].(*DB)
// db is now a *DB value

Effective Go has a section on this.


You would need type assertion to convert the interface (db := context.Keys["DB"]) into something useful. See for example this post: convert interface{} to int in Golang


I don't think context should be used as DI container: https://golang.org/pkg/context/

Package context defines the Context type, which carries deadlines, cancellation signals, and other request-scoped values across API boundaries and between processes.

I would rather use:

package public

type PublicController struct {
        Database *DB
}

func (c *PublicController) GetCurrentVotePack(context *gin.Context) {
        votePack, err := c.Database.GetVotePack("c5039ecd-e774-4c19-a2b9-600c2134784d")
        if err != nil{
                context.String(404, "Votepack Not Found")
        }
        context.JSON(200, votePack)
}

and configure your controller in main:

func main() {
        pCtrl := PublicController { Database: models.NewDB("<connectionstring>") }

        router := gin.New()
        router.GET("/public/current-vote-pack", pCtrl.GetCurrentVotePack)
        router.Run(":1000")
}