使用具有单独模型和服务包的单例数据库类

时间:2018-03-22 20:43:26

标签: go

我的问题与How to create singleton DB class in GoLang类似,但我无法使用单独的模型和服务包。

项目/ LIB /数据库/ mysql.go:

package database

import (
    "fmt"

    _ "github.com/go-sql-driver/mysql"
    "github.com/jinzhu/gorm"
)

type Manager struct {
    *gorm.DB
}

var Mgr *Manager

func init() {
    dsn := MysqlConnectionString("parseTime=true")
    tablePrefix := "demo"
    var err error

    gorm.DefaultTableNameHandler = func(db *gorm.DB, defaultTableName string) string {
        return fmt.Sprintf("%v_%v", tablePrefix, defaultTableName)
    }

    db, err := gorm.Open("mysql", dsn)
    if err != nil {
        panic(err)
    }

    Mgr = &Manager{db}
}

项目/ lib中/模型/ retailer_keys.go

package models

import (
    "fmt"
    "project/lib/database"
    "time"
)

type RetailerKeysInterface interface {
    RetailerKeys() ([]*RetailerKey, error)
}

type DB struct {
    database.Manager
}

type RetailerKey struct {
    Id         int        `json:"id"`
    RetailerId int        `json:"retailer_id"`
    Key        string     `json:"key"`
    Enabled    *bool      `json:"enabled"`
    CreatedAt  *time.Time `json:"created_at"`
    UpdatedAt  *time.Time `json:"updated_at"`
}

func (db *DB) RetailerKeys() ([]*RetailerKey, error) {
    var keys []*RetailerKey
    if err := db.Find(&keys).Error; err != nil {
        return nil, err
    }
    return keys, nil
}

项目/ lib目录/服务/ retailer_keys.go

import (
    "fmt"
    "strings"

    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/apigateway"
    "gopkg.in/volatiletech/null.v6"

    "project/lib/models"
    "project/lib/services/api_keys"
)

func GetKeys() ([]*models.RetailerKey, error) {
    var q models.RetailerKeysInterface

    keys, err := q.RetailerKeys()
    if err != nil {
        return nil, err
    }
    return keys, nil
}

func CreateKey(id int) (models.RetailerKey, error) {
    ...
}

然后可以在我的主包中使用它,如:

package main

import (
    "context"
    "encoding/json"
    // "reflect"
    "fmt"

    "github.com/aws/aws-lambda-go/events"
    "github.com/aws/aws-lambda-go/lambda"

    _ "project/lib/config"
    "project/lib/services"
)

func Handler(ctx context.Context, request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
    statusCode := 200

    keys, err := services.GetKeys()
    if err != nil {
        statusCode = 400
    }
    body, _ := json.Marshal(keys)

    return events.APIGatewayProxyResponse{
        Body:       string(body),
        StatusCode: statusCode,
    }, nil
}

...

我希望能够在我的模型中嵌入Manager类型的相关子集。

编辑: 根据评论中的反馈编辑了问题/代码。

这给了我一个错误:runtime error: invalid memory address or nil pointer dereference

1 个答案:

答案 0 :(得分:0)

我肯定误解了界面。经过A Tour of Go之后,它开始变得更清晰,它们如何融合在一起。

这就是我最终为那些经历同样事情的人做的事情。我会留下原来的问题,以便您可以看到差异。

项目/ LIB /数据库/ mysql.go:

package database

import (
    "fmt"
    "log"

    _ "github.com/go-sql-driver/mysql" // Needed for gorm
    "github.com/jinzhu/gorm"
)

var Manager *gorm.DB

func init() {
    var err error

    dsn := MysqlConnectionString("parseTime=true")
    tablePrefix := "qcommerce"

    gorm.DefaultTableNameHandler = func(db *gorm.DB, defaultTableName string) string {
        return fmt.Sprintf("%v_%v", tablePrefix, defaultTableName)
    }

    Manager, err = gorm.Open("mysql", dsn)
    if err != nil {
        log.Fatal(err)
    }

    if err := Manager.DB().Ping(); err != nil {
        log.Fatal(err)
    }
}

项目/ lib中/模型/ retailer_keys.go

package models

import (
    "project/lib/database"
    "time"
)

type QRetailerKeys interface {
    Insert() error
    Find() error
}

type RetailerKey struct {
    ID                  int        `json:"id"`
    RetailerID          int        `json:"retailer_id"`
    Retailer            Retailer   `json:"retailer"`
    Key                 string     `json:"key"`
    Enabled             bool       `json:"enabled" gorm:"DEFAULT:true"`
    CreatedAt           *time.Time `json:"created_at"`
    UpdatedAt           *time.Time `json:"updated_at"`
}

// RetailerKeys returns a slice of all keys in table
func RetailerKeys() ([]*RetailerKey, error) {
    var keys []*RetailerKey
    if err := database.Manager.Find(&keys).Error; err != nil {
        return nil, err
    }
    return keys, nil
}

func (r *RetailerKey) Find() error {
    ...
}

// Create a new key
func (r *RetailerKey) Create() error {
    return database.Manager.Create(&r).Error
}

项目/ lib目录/服务/ retailer_keys.go

package services

import (
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/session"
    // "github.com/aws/aws-sdk-go/service/apigateway"

    "partners.drinks.com/lib/models"
    "partners.drinks.com/lib/services/api_keys"
)

func sessionBuilder() *session.Session {
    config := &aws.Config{
        Region: aws.String("us-west-2"),
    }
    session := session.Must(session.NewSession(config))
    return session
}

func GetKeys() ([]*models.RetailerKey, error) {
    keys, err := models.RetailerKeys()
    if err != nil {
        return nil, err
    }
    return keys, nil
}

func CreateKey(id int) (models.RetailerKey, error) {
    apikeys := &api_keys.ApiKeyBuilder{}
    base64Key := apikeys.GenUUID().GenKey().Base64

    var key = models.RetailerKey{
        RetailerID: id,
        Key: base64Key,
        Enabled: func(b bool)
    }

    if err := key.Create(); err != nil {
        return models.RetailerKey{}, err
    }
    ...

    return key, nil
}

我用它像:

package main

import (
    "context"
    "encoding/json"

    "github.com/aws/aws-lambda-go/events"
    "github.com/aws/aws-lambda-go/lambda"

    _ "partners.drinks.com/lib/config"
    "partners.drinks.com/lib/services"
)


func Handler(ctx context.Context, request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
    statusCode := 200

    keys, err := services.GetKeys()
    if err != nil {
        statusCode = 400
    }
    body, _ := json.Marshal(keys)

    return events.APIGatewayProxyResponse{
        Body:       string(body),
        StatusCode: statusCode,
    }, nil
}

...

感谢@mkopriva对评论中的链接资源。