Ho appena iniziato a provare Go e sto cercando di implementare di nuovo un server API scritto nel nodo con esso.Go and Gin: aggirare la struttura per il contesto del database?
Ho raggiunto un ostacolo con il tentativo di utilizzare l'iniezione delle dipendenze per aggirare un contesto di database come un middleware di gin. Finora ho impostato in su come questo:
main.go:
package main
import (
"fmt"
"runtime"
"log"
"github.com/gin-gonic/gin"
"votesforschools.com/api/public"
"votesforschools.com/api/models"
)
type DB struct {
models.DataStore
}
func main() {
ConfigRuntime()
ConfigServer()
}
func Database(connectionString string) gin.HandlerFunc {
dbInstance, err := models.NewDB(connectionString)
if err != nil {
log.Panic(err)
}
db := &DB{dbInstance}
return func(c *gin.Context) {
c.Set("DB", db)
c.Next()
}
}
func ConfigRuntime() {
nuCPU := runtime.NumCPU()
runtime.GOMAXPROCS(nuCPU)
fmt.Printf("Running with %d CPUs\n", nuCPU)
}
func ConfigServer() {
gin.SetMode(gin.ReleaseMode)
router := gin.New()
router.Use(Database("<connectionstring>"))
router.GET("/public/current-vote-pack", public.GetCurrentVotePack)
router.Run(":1000")
}
modelli/db.go
package models
import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
)
type DataStore interface {
GetVotePack(id string) (*VotePack, error)
}
type DB struct {
*sql.DB
}
func NewDB(dataSource string) (*DB, error) {
db, err := sql.Open("mysql", dataSource)
if err != nil {
return nil, err
}
if err = db.Ping(); err != nil {
return nil, err
}
return &DB{db}, nil
}
modelli/votepack.go
package models
import (
"time"
"database/sql"
)
type VotePack struct {
id string
question string
description string
startDate time.Time
endDate time.Time
thankYou string
curriculum []string
}
func (db *DB) GetVotePack(id string) (*VotePack, error) {
var votePack *VotePack
err := db.QueryRow(
"SELECT id, question, description, start_date AS startDate, end_date AS endDate, thank_you AS thankYou, curriculum WHERE id = ?", id).Scan(
&votePack.id, &votePack.question, &votePack.description, &votePack.startDate, &votePack.endDate, &votePack.thankYou, &votePack.curriculum)
switch {
case err == sql.ErrNoRows:
return nil, err
case err != nil:
return nil, err
default:
return votePack, nil
}
}
Quindi, con tutto quanto sopra, voglio passare i modelli.DataSource in giro come un middleware in modo che sia possibile accedervi in questo modo:
pubblico/public.go
package public
import (
"github.com/gin-gonic/gin"
)
func GetCurrentVotePack(context *gin.Context) {
db := context.Keys["DB"]
votePack, err := db.GetVotePack("c5039ecd-e774-4c19-a2b9-600c2134784d")
if err != nil{
context.String(404, "Votepack Not Found")
}
context.JSON(200, votePack)
}
Tuttavia ottengo public\public.go:10: db.GetVotePack undefined (type interface {} is interface with no methods)
Quando ho ispezionare nel debugger (usando WebStorm con plugin) il db è solo un oggetto vuoto. Sto cercando di essere buono ed evito l'uso di variabili globali
Perfetto, sembrava risolverlo. –
Mentre questo risolve il problema, mi sembra un pessimo design. Affidarsi a qualcuno che mette le strutture dell'interfaccia {} in un contesto generico non sembra un vero e proprio progetto fortemente tipizzato. Immagino che la maggior parte dell'errore sia dovuto al fatto che gin si aspetta una funzione per il metodo handle invece di un'interfaccia –
@SnoProblem È un buon modo per passare la connessione al database tramite Context? C'è qualche altro modo e? –