gorm注册callback原理

作者: raisecrow | 来源:发表于2019-09-29 14:11 被阅读0次

背景:

在做项目时,遇到一个监控需求,就是每次执行sql语句都要上报耗时到prometheus。首先想到的是在写业务逻辑时每次执行sql语句都自己上报,但这样会侵入业务代码,而且有的人会忘了上报,或者上报格式不规范,所以想到将上报逻辑封装到gorm的框架里。

具体原理:

gorm执行sql语句都是通过注册callback函数实现的。如执行如下语句时:

image

会依次执行、queryCallback、queryCallback、queryCallback,这是因为gorm初始化时注册了这几个函数:

image

如果我们想注册些自己写的函数呢?而且想控制函数调用的顺序,比如想自己注册一个函数func2,而且在queryCallback之后,queryCallback之前调用,那改怎么办?其实可以这样:

image

其中after函数的参数就是注册queryCallback时指定的名字,Register的第一个参数callbackName就是你要注册的函数的名字,callbackName要保持唯一性,否则后面Register的会覆盖前面的。

至此,调first函数时,将会依次调这几个函数:queryCallback、func、queryCallback、queryCallback

源码分析:

callback的定义。上面的first语句会把callback func append到queries字段里。

// Callback is a struct that contains all CRUD callbacks
//   Field `creates` contains callbacks will be call when creating object
//   Field `updates` contains callbacks will be call when updating object
//   Field `deletes` contains callbacks will be call when deleting object
//   Field `queries` contains callbacks will be call when querying object with query methods like Find, First, Related, Association...
//   Field `rowQueries` contains callbacks will be call when querying object with Row, Rows...
//   Field `processors` contains all callback processors, will be used to generate above callbacks in order
type Callback struct {
    logger     logger
    creates    []*func(scope *Scope)
    updates    []*func(scope *Scope)
    deletes    []*func(scope *Scope)
    queries    []*func(scope *Scope)
    rowQueries []*func(scope *Scope)
    processors []*CallbackProcessor
}

这个就是first的源码,最后一行调callCallbacks时就会依次调queries的func。

// First find first record that match given conditions, order by primary key
func (s *DB) First(out interface{}, where ...interface{}) *DB {
    newScope := s.NewScope(out)
    newScope.Search.Limit(1)

    return newScope.Set("gorm:order_by_primary_key", "ASC").
        inlineCondition(where...).callCallbacks(s.parent.callbacks.queries).db
}
func (scope *Scope) callCallbacks(funcs []*func(s *Scope)) *Scope {
    defer func() {
        if err := recover(); err != nil {
            if db, ok := scope.db.db.(sqlTx); ok {
                db.Rollback()
            }
            panic(err)
        }
    }()
    for _, f := range funcs {
        (*f)(scope)
        if scope.skipLeft {
            break
        }
    }
    return scope
}

参考文献:

http://gorm.book.jasperxu.com/callbacks.html

https://gorm.io/docs/hooks.html

Gin实践 连载十 定制 GORM Callbacks

相关文章

  • gorm注册callback原理

    背景: 在做项目时,遇到一个监控需求,就是每次执行sql语句都要上报耗时到prometheus。首先想到的是在写业...

  • gorm源码1 目录分析

    gorm目录文件如下: 主要文件是callback main scope search field dialect...

  • jsonp原理

    JSONP原理: 首先在客户端注册一个callback, 然后把callback的名字传给服务器。 此时,服务器先...

  • jsonp

    Jsonp原理: 首先在客户端注册一个callback, 然后把callback的名字传给服务器。 此时,服务器先...

  • golang gorm(一)---gorm入门示例

    gorm是go语言的一个orm框架,框架的原理和思想在这里就不做详细介绍了,我主要演示一下gorm的实际使用。 开...

  • JSONP小原理

    首先在客户端注册一个callback, 然后把callback的名字传给服务器。此时,服务器先生成 json 数据...

  • js jsbridge

    做了一段时间RN 先说RN中方法调用原理 目前没碰上原生带callback调用js,只有js带callback调用...

  • github上Go项目star排名21~30

    Gorm[https://github.com/go-gorm/gorm]:https://github.com/...

  • gorm Update方法

    gorm[https://github.com/go-gorm/gorm/],字节jinzhu[https://g...

  • Binder通信传输callback时,为什么能实现unRegi

    问题描述 Android开发中,客户端通过Binder向服务端注册 / 去注册 callback,是我们常用的开发...

网友评论

    本文标题:gorm注册callback原理

    本文链接:https://www.haomeiwen.com/subject/qrtqyctx.html