geektutu / blog

极客兔兔的博客,Coding Coding 创建有趣的开源项目。
https://geektutu.com
Apache License 2.0
166 stars 21 forks source link

动手写ORM框架 - GeeORM第五天 实现钩子(Hooks) | 极客兔兔 #77

Open geektutu opened 4 years ago

geektutu commented 4 years ago

https://geektutu.com/post/geeorm-day5.html

7天用 Go语言/golang 从零实现 ORM 框架 GeeORM 教程(7 days implement golang object relational mapping framework from scratch tutorial),动手写 ORM 框架,参照 gorm, xorm 的实现。通过反射(reflect)获取结构体绑定的钩子(hooks),并调用;支持增删查改(CRUD)前后调用钩子。

xiaoxfan commented 4 years ago

全是反射 看懵逼了 大佬真厉害

shiluoye commented 3 years ago

用MethodByName(method)实在太骚了,为什么不用interface,gorm的hook机制就是通过interface实现的

geektutu commented 3 years ago

@shiluoye 嗯,这个地方使用接口的确更合适。判断是否实现了某个接口,实现了则调用。之前合入过一个 PR,ITableName 自定义表名的,如果实现了该接口,就使用 ITableName 返回的字符串作为表名。

feixintianxia commented 3 years ago

@shiluoye 用MethodByName(method)实在太骚了,为什么不用interface,gorm的hook机制就是通过interface实现的
我的理解是:


type IBeforeQuery interface {
BeforeQuery(s *Session) error
}

type IAfterQuery interface { AfterQuery(s *Session) error } ..... 等等

//然后修改CallMethod func (s *Session) CallMethod(method string, value interface{}) { ... if i, ok := dest.(IBeforQuery); ok == true { i. BeforeQuery(s) } ... return }

geektutu commented 3 years ago

@feixintianxia 正解~

DurantVivado commented 2 years ago

脱敏 desensitization ,比较敏感的信息,比如密码,在提交到服务器后,应该变为"**",从而保护隐私。此外,此类功能函数并未直接在包内定义,而是在调用时候定义,像"钩子"钓鱼一样,这里的鱼就是用户定义函数。

MrBear2018 commented 2 years ago

改成接口的话, 只需要对hook文件修改如下: 自测没问题, 我写的不够优雅, 有好的实现也请大家分享出来.

// Hooks constants
const (
    BeforeQuery  = "BeforeQuery"
    AfterQuery   = "AfterQuery"
    BeforeUpdate = "BeforeUpdate"
    AfterUpdate  = "AfterUpdate"
    BeforeDelete = "BeforeDelete"
    AfterDelete  = "AfterDelete"
    BeforeInsert = "BeforeInsert"
    AfterInsert  = "AfterInsert"
)

type IAfterQuery interface {
    AfterQuery(s *Session) error
}

type IBeforeInsert interface {
    BeforeInsert(s *Session) error
}

// CallMethod calls the registered hooks
func (s *Session) CallMethod(method string, value interface{}) {
    param := reflect.ValueOf(value)
    switch method {
    case AfterQuery:
        if i, ok := param.Interface().(IAfterQuery); ok {
            i.AfterQuery(s)
        }
    case BeforeInsert:
        if i, ok := param.Interface().(IBeforeInsert); ok {
            i.BeforeInsert(s)
        }
    default:
        panic("unsupported hook method")
    }
    return
}