在 Go 项目中优雅的使用 gorm v2


当前第2页 返回上一页

如何优雅的传递 tx 参数?Go 里面没有重载,这种情况有个比较通用的方案:Context。使用 Context 后续如果要做链路追踪、超时控制等也很方便扩展

gorm 链路追踪可参考 github 上大佬的实现

我们只需要把 GetDB 改改,尝试从 ctx 中获取 tx,如果存在则不需要新建 session,直接使用传递的 tx。这个有个小技巧,使用结构体而不是字符串作为 ctx 的 key,可以保证 key 的唯一性。代码如下:

func GetDB(ctx context.Context) *gorm.DB {
    iface := ctx.Value(ctxTransactionKey{})

    if iface != nil {
        tx, ok := iface.(*gorm.DB)
        if !ok {
            log.Panicf("unexpect context value type: %s", reflect.TypeOf(tx))
            return nil
        }

        return tx
    }

    return globalDB.WithContext(ctx)
}

在事务上做一下 context 的封装:

func Transaction(ctx context.Context, fc func(txctx context.Context) error) error {
    db := globalDB.WithContext(ctx)

    return db.Transaction(func(tx *gorm.DB) error {
        txctx := CtxWithTransaction(ctx, tx)
        return fc(txctx)
    })
}

使用事务:

ownerId := "xxx"
err := Transaction(context.Background(), func(txctx context.Context) error {
    pet, err := NewPetDb(txctx).Create(&petmodel.Pet{
        Name: "xxx",
        Age:  1,
        Sex:  "female",
    })
    if err != nil {
        return err
    }

    _, err = NewOwner_PetDb(txctx).Create(&petmodel.Owner_Pet{
        OwnerId: ownerId,
        PetId:   pet.Id,
    })
    return err
})

Hooks & Callbacks

gorm 提供 Hooks 功能,可以在某些扩展点执行钩子函数,例如创建前生成 uuid :

func (u *Pet) BeforeCreate(tx *gorm.DB) error {
    u.Id = NewUlid()
    return nil
}

但是 Hooks 是针对某个 model,如果需要对所有 model,可以使用 Callbacks 。

func registerCallback(db *gorm.DB) {
    // 自动添加uuid
    err := db.Callback().Create().Before("gorm:create").Register("uuid", func (db *gorm.DB) {
        db.Statement.SetColumn("id", NewUlid())
    })
    if err != nil {
        log.Panicf("err: %+v", errx.WithStackOnce(err))
    }
}

项目完整代码:https://github.com/win5do/go-...


本文来自:Segmentfault

感谢作者:.container .card .information strong

查看原文:在 Go 项目中优雅的使用 gorm v2

返回前面的内容

相关阅读 >>

Gocn酷Go推荐】Go 类型转换神器 cast库

Go语言学习(四):数组和切片

leetcode1047 删除字符串中的所有相邻重复项 Golang

Go语言基础

Go build和Go install的区别

Go - Go build 各种系统下的可执行文件

Go html/template

Golang怎么判断数组是否为空

在 bigcache 中存储任意类型(interface{})

Go 并发编程-共享变量

更多相关阅读请进入《Go》频道 >>




打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...

    正在狠努力加载,请稍候...