2016-02-27 9 views
5

Tôi vừa mới bắt đầu dùng thử Go và tôi đang tìm cách triển khai lại máy chủ API được viết bằng nút với nó.Go and Gin: Vượt qua cấu trúc cho bối cảnh cơ sở dữ liệu?

Tôi đã gặp trở ngại với việc cố gắng sử dụng tính năng tiêm phụ thuộc để truyền xung quanh ngữ cảnh cơ sở dữ liệu như một phần mềm trung gian gin. Cho đến nay tôi đã thiết lập nó như thế này:

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

mô hình/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 
} 

mô hình/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 
     } 
} 

Vì vậy, với tất cả những điều trên, tôi muốn truyền các mô hình.DataSource xung quanh như một phần mềm trung gian để nó có thể được truy cập như thế này:

công cộng/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) 
} 

Tuy nhiên tôi nhận được public\public.go:10: db.GetVotePack undefined (type interface {} is interface with no methods)

Khi tôi kiểm tra trong trình gỡ lỗi (sử dụng Webstorm với plugin) db chỉ là một đối tượng có sản phẩm nào. Tôi đang cố gắng làm tốt và tránh sử dụng biến toàn cầu

Trả lời

6

Các giá trị trong vòng context.Keys là tất cả các loại interface{}, vì vậy db sẽ không thể gọi các phương thức từ loại *DB cho đến khi nó được chuyển đổi trở lại loại đó.

Cách an toàn:

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

Cách ít an toàn, mà sẽ hoảng sợ nếu context.Keys["DB"] không phải là một giá trị kiểu *DB:

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

Effective Go có một phần về vấn đề này.

+0

Hoàn hảo, dường như giải quyết nó. –

+0

Trong khi điều này giải quyết vấn đề, nó trông giống như thiết kế rất xấu với tôi. Dựa vào một người nào đó đặt giao diện {} trong bối cảnh chung không giống như thiết kế được đánh máy đúng đắn. Tôi đoán hầu hết các lỗi là vì gin hy vọng một chức năng cho phương pháp xử lý thay vì một giao diện –

+0

@SnoProblem Đó là cách tốt để vượt qua kết nối cơ sở dữ liệu thông qua bối cảnh? Còn cách nào khác không&? –

Các vấn đề liên quan