使用单独的数据库类和单独的模型和服务包 [英] Using a singleton database class with separate models and services packages

查看:158
本文介绍了使用单独的数据库类和单独的模型和服务包的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题类似于如何创建单例DB类在GoLang 中,但是我无法使它与单独的模型和服务包一起工作。



project / lib / database / mysql.go:

 包数据库

导入(
fmt

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


类型经理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 {
恐慌(错误)
}

Mgr =& Manager {db}
}

project / lib / models / retailer_keys.go

 包装模型

导入(
fmt
project / lib / database
time


类型RetailerKeysInterface接口{
RetailerKeys()([] * RetailerKey ,错误)
}

类型DB结构{
database.Manager
}

类型RetailerKey结构{
Id int `json:id`
RetailerId int`json:retailer_id`
键字符串`json:key`
启用* bool`json:enabled`
CreatedAt * time.Time`json:created_at`
UpdatedAt * time.Time`json:updated_at`
}

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

项目/ lib / services / retailer_keys.go

 导入(
fmt
字符​​串

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

项目/ 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键,零
}

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


$ b

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

 包主

导入(
上下文
encoding / json
//反映
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(键)

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

...

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

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

这给我一个错误:运行时错误:无效的内存地址或零指针解引用

解决方案

我绝对误解了界面。经过A Tour of Go之后,它开始变得更加清晰,它是如何融合在一起的。



这是我最终为所有经历过同样事情的人做的。



project / lib / database / mysql.go:

 包数据库

导入(
fmt
log

_ github.com/go-sql-driver/mysql//需要gorm
github.com/jinzhu/gorm


var Manager * gorm.DB

func init(){
var err error
$ b dsn:= MysqlConnectionString(parseTime = true)
tablePrefix:=qcommerce

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

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

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

project / lib / models / retailer_keys.go

 包模型

导入(
project / lib / database
time


类型QRetailerKeys接口{
Insert()错误
Find()错误
}
$ b $类型RetailerKey结构{
ID int`json:id`
RetailerID int`json:retailer_id`
零售商零售商` json:retailer
键字符串`json:键
启用bool`json:启用gorm:DEFAULT:true`
CreatedAt * time.Time`json :created_at`
UpdatedAt * time.Time`json:updated_at`
}

// RetailerKeys返回表中所有键的切片
func RetailerKeys()([] * RetailerKey,error){
var keys [] * RetailerKey
if err:= database.Manager.Find(&键).Error; err!= nil {
return nil,err
}
return key,nil
}

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

//创建一个新键
func(r * RetailerKey)Create()错误{
return database.Manager。创建(& r).Error
}

project / lib / services / retailer_keys。 go

 包服务

导入(
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){
键,err:= models.RetailerKeys()
if err!= nil {
return nil,err
}
返回键,零
}

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

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

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

返回键,零
}

我使用它:

  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
合作伙伴.drinks.com / lib / services



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

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

返回events.APIGatewayProxyResponse {
正文:string(body),
StatusCode:statusCode,
},nil
}

...

感谢@m kopriva为注释中的链接资源。


My question is similar to How to create singleton DB class in GoLang but I'm having trouble getting it to work with separate models and services packages.

project/lib/database/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}
}

project/lib/models/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
}

project/lib/services/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) {
    ...
}

Then be able to use it in my main package like:

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
}

...

I'd like to be able to embed the relevant subset of the Manager type in my models.

EDIT: Edited the question/code based on feedback in comments.

This gives me an error: runtime error: invalid memory address or nil pointer dereference.

解决方案

I was definitely misunderstanding interfaces in go. After going through A Tour of Go it started to become clearer how it all fits together.

This is that I ended up doing for anyone that is going through the same thing. I'll leave the original question up so you can see the differences.

project/lib/database/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)
    }
}

project/lib/models/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
}

project/lib/services/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
}

I use it like:

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
}

...

Thanks to @mkopriva for the linked resources in the comments.

这篇关于使用单独的数据库类和单独的模型和服务包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆