[封裝]實戰gorm

由於gorm不僅支持數據庫讀寫操作,且以面向對象的編碼方式實現數據庫讀寫。本片文章從實際開發中所遇問題和新的需要,對gorm進行一次封裝操作,以此來加快開發速度。

首先介紹代碼架構:

|-----------------------
|- component
|-- db.go
|-- model.go
|-- test.go
|- include
|-- container.go
|-- db.go
|- init
|-- init.go
|- model
|-- bean
|--- messageRegister.go
|-- messageRegister.go
|- test
|-- messageRegister.go
|- main.go
|-----------------------

a. 入口文件: main.go

package main

import _ "./init"
import "./test"

func main() {
    test.TMessageRegister()
}

b. 編寫基礎結構體和接口(component)

   (1)  數據庫連接相關, db.go

package component

import "github.com/jinzhu/gorm"

type SwyModel struct {
    *gorm.DB    //鏈接實例
    TableName           string      //數據庫名
}

   (2)  數據實體相關, model.go 

package component

import (
    "encoding/json"

    "github.com/jinzhu/gorm"
)

//數據庫增刪改查操作封裝
type Curd interface {

}

type Transaction interface {

}

type DpModel struct {
    Curd
    Transaction
    gorm.Model
}

func translate(out interface{}, v interface{}) (interface{}, error) {
    var (
        err error
        ms = make([]byte, 0, 64)
    )
    ms, err = json.Marshal(v)
    if err != nil {
        return nil, err
    }
    err = json.Unmarshal(ms, out)
    if err != nil {
        return nil, err
    }
    return out, nil
}

func (s *DpModel) Translate(out interface{}, v interface{}) (interface{}, error) {
    return translate(out, v)
}

   (3)  測試相關, test.go

package component

type DpTest struct {

}

c. 系統初始化,init.go

package init

import (
    _ "../include"

)

d. 依賴包加載(include)

    (1)初始化容器

//容器, 用於管理中間件
package include

import (
	"fmt"
	"sync"
)

type Container struct {
	mux sync.Mutex
	mds map[string]interface{}
}

var Cont *Container = &Container{
	sync.Mutex{},
	make(map[string]interface{}, 8),
}

func (c *Container) Register(n string, sl interface{}) {
	c.mux.Lock()
	defer c.mux.Unlock()
	_, ok := c.mds[n]
	if !ok {
		c.mds[n] = sl
	}
}

func (c *Container) Get(n string) (interface{}, error) {
	sl, ok := c.mds[n]
	if !ok {
		return nil, fmt.Errorf("未找到單例`%v`", n)
	}
	return sl, nil
}

    (2)初始化數據庫連接實例

package include

import (
    "fmt"

    _ "github.com/jinzhu/gorm/dialects/mysql"
    "github.com/jinzhu/gorm"
)

func init() {
    dc := struct {
        User    string
        Password string
        Host   string
        Port   string
        DBName string
        Option string
    }{
        `root`,
        `chuyinwl01`,
        `localhost`,
        `3306`,
        `go`,
        `charset=utf8mb4&parseTime=true`,
    }
    //依賴配置項
    dsn :=  fmt.Sprintf(
        "%s:%s@(%s:%s)/%s?%s",
        dc.User,
        dc.Password,
        dc.Host,
        dc.Port,
        dc.DBName,
        dc.Option,
    )
    db, err := gorm.Open("mysql", dsn)
    if err != nil {
        panic(fmt.Sprintf("數據庫初始化異常, error:`%v`", err))
    }
    Cont.Register("db", db)
}

func GetDB(db interface{}) *gorm.DB {
    if db == nil {
        panic("獲取gorm.DB對象失敗, 傳入nil!")
    }
    gd := db.(*gorm.DB)
    return gd
}

e. 編寫數據實體(model)

   (1) 編寫數據實體(bean)

package bean

import (
    "../../component"
)

type MessageRegister struct {
    component.DpModel
    Type int `gorm:"column:type" json:"type"`
    Desc string `gorm:"column:desc" json:"desc"`
}

func (s *MessageRegister) TranslateSelf(v interface{}) *MessageRegister {
    var m interface{}
    var err error
    var ok bool
    var message *MessageRegister

    if m, err = s.Translate(s, v); err != nil {
        //todo log
        return nil
    }
    if message, ok = m.(*MessageRegister); !ok {
        //todo log
    }
    return message
}


   (2) 編寫實體操作對象

package model

import (
    "fmt"

    "../component"
    "../include"
)

type MessageRegisterModel struct {
    component.SwyModel
}

func NewMessageRegister() *MessageRegisterModel {
    db, err := include.Cont.Get("db")
    if err != nil {
        panic(fmt.Sprintf("內部錯誤, error:`%v`", err))
    }
    gd := include.GetDB(db)
    if gd == nil {
        panic("內部錯誤, 數據庫單例類型異常")
    }
    tableName := "go_register"
    return &MessageRegisterModel{
        component.SwyModel{
                gd.Table(tableName),
                tableName,
        },
    }
}

f. 編寫測試用例, messageRegister.go

package test

import (
    "../component"
    "fmt"
    "github.com/jinzhu/gorm"
)
import "../model"
import "../model/bean"

type MessageRegisterTest struct {
    component.DpTest
}

func (s *MessageRegisterTest) Test() {
    var modelMessageRegister = model.NewMessageRegister()
    var messageRegister = &bean.MessageRegister{}

    //----------------------- 創建一條記錄
    messageRegister.Type = 1
    messageRegister.Desc = `dora hope`
    if err := modelMessageRegister.Create(messageRegister).Error; err != nil {
       panic(fmt.Sprintf("數據庫寫測試失敗, err:`%v`\n", err))
    }
    fmt.Println(`數據庫寫測試成功`)

    //----------------------- 查看一條記錄
    //id := 1
    //if err := modelMessageRegister.Where(`id = ?`, id).First(messageRegister).Error; err != nil {
    //    if gorm.IsRecordNotFoundError(err) {
    //        panic(fmt.Sprintf("未找到記錄, err:`%v`\n", err))
    //    }
    //    panic(fmt.Sprintf("數據庫讀測試失敗, err:`%v`\n", err))
    //}
    //fmt.Printf("message is `%v`\n", messageRegister)

    //----------------------- json轉移處理(並沒有對記錄的生成等時間進行轉移)
    //_ = modelMessageRegister
    //j := map[string]interface{} {
    //    `id`: 1,
    //    `type`: 1,
    //    `desc`: `dora hope`,
    //}
    //if messageRegister.Translate(messageRegister, j); messageRegister == nil {
    //    panic(fmt.Sprintf("數據實體轉義失敗\n"))
    //}
    //fmt.Printf("數據庫實體轉移成功, message:`%v`\n", messageRegister)
}

func TMessageRegister() {
    t := &MessageRegisterTest{}
    t.Test()
}

以上就是本篇文章的所介紹的內容,從測試中可看出,開發時,對某張表數據的操作起來還是很簡單的,雖然只是對gorm簡單的封裝,但是還是挺實用的。所以,參考本文章,編寫數據實體時,只需要實現數據實體結構和數據實體操作對象。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章