The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
cc959798

为什么 Go 中的 ORM 框架使用起来感觉比较怪异

  •  
  •   cc959798 · Jul 14, 2018 · 15960 views
    This topic created in 2889 days ago, the information mentioned may be changed or developed.

    最近研究 Go,做业务系统必然要用到 ORM,毕竟数据库操作太频繁了鞋 SQL 效率太低了

    之前用过很多 ORM,比如 JAVA 中的 hibernate,Python 中的 sqlalchemy,PHP 中的 Yii,感觉 ORM 其实都是大同小异 上面的几乎也是类似的使用方式 但是到了 Go,这里感觉画风骤变,了解了 gorm 和 xorm (这两个其实挺像的),里面不在像之前的通过 model 或者 db 进行 find 查询只需要传入条件返回一个查到的对象,2️⃣必须先要 new 一个对象,然后通过指针传入进去,框架也是感觉比较简单的

    46 replies    2018-07-19 15:28:11 +08:00
    looplj
        1
    looplj  
       Jul 14, 2018
    你仔细想想,你不 new 一个给它,它怎么返回一个你要的对象给你
    gowk
        2
    gowk  
       Jul 14, 2018
    ORM 倾向于让系统变得复杂,直接用 sqlx 就好了
    Cbdy
        3
    Cbdy  
       Jul 14, 2018 via Android
    直接写 SQL,然后 bind 参数,这样是坠吼的
    kunluanbudang
        4
    kunluanbudang  
       Jul 14, 2018   ❤️ 1
    Go 粉丝 /布道者, 倾向于批判楼主

    ( Go , 整体还不错, 用起来也非常爽,

    但是 Go 粉丝, 一般喜欢无脑吹捧一些陋习, 我比较反感这个 )
    Muninn
        5
    Muninn  
       Jul 14, 2018
    go 也可以给你返回给 map[string]interface{},然而不好用啊。。。

    你 new 一个给你智能的填进去反而后边省事了,预定义好,不用你取到后再处理了。
    monsterxx03
        6
    monsterxx03  
       Jul 14, 2018 via iPhone
    go 的 orm 不好用,试试 squirrel + sqlx
    guoziyan
        7
    guoziyan  
       Jul 14, 2018
    所有的 orm 没有一个直观好用的(所有语言)
    janxin
        8
    janxin  
       Jul 14, 2018 via iPad
    实际上因为没用过 c++/rust 的 orm 吧,go 没有那种贴近动态语言的运行时功能,只能做到这种地步了
    lhx2008
        9
    lhx2008  
       Jul 14, 2018 via Android
    @guoziyan springboot 的 springjpa+heibernate 用过了吗
    q397064399
        10
    q397064399  
       Jul 14, 2018
    @guoziyan #7 springdata jpa 了解一下
    cc959798
        11
    cc959798  
    OP
       Jul 14, 2018
    @ZSeptember 如果 model 是结构体的话,直接返回一个结构体 变量或者自己内部 new 一个不就可以了
    cc959798
        12
    cc959798  
    OP
       Jul 14, 2018
    @janxin 都没见过 C++的 ORM
    looplj
        13
    looplj  
       Jul 14, 2018 via Android
    @cc959798 你 new 一个看看,想想
    boyhailong
        14
    boyhailong  
       Jul 14, 2018
    那可以自己造轮子,用脚本生成代码吧 像 protobuf 那样,虽然很麻烦,加载、查询、保存都可以自己定制。。。。
    公司项目 C++就是那样,不然要麻烦哭
    qsnow6
        15
    qsnow6  
       Jul 14, 2018
    django orm 了解一下
    looplj
        16
    looplj  
       Jul 14, 2018 via Android
    @janxin rust 还可以用 derive,还好
    xiaqi
        17
    xiaqi  
       Jul 14, 2018 via Android
    我怎么感觉写 sql 效率还更高呢?
    orm 一些复杂的操作是操作不了的,写 sql,我甚至可以放个存储过程进去,经管这个有时候不推荐。而且写 sql 通用,换了语言也不是很担心,相反,orm 换了语言,有些差别可就大了,你得再去学一遍 orm。
    cc959798
        18
    cc959798  
    OP
       Jul 14, 2018
    @Muninn 为什么不直接返回一个 model,填充好的
    luob
        19
    luob  
       Jul 14, 2018
    gorm 作者的意思是为了保持 api 一致
    所有的操作都返回 db 实例,就可以愉快地链式调用,查询结果这种东西只能委屈一下先 new 一个,然后传进去塞值
    dodo2012
        20
    dodo2012  
       Jul 14, 2018
    @ZSeptember derive 用了下,感觉挺难用啊,难道是姿势不对
    bigpigeon
        21
    bigpigeon  
       Jul 14, 2018
    有一个 orm 方案是生成代码,因为 go 是强类型的,并且不支持模板,所以没法通过返回值取值
    looplj
        22
    looplj  
       Jul 14, 2018
    @dodo2012 derive 就是用 macro 实现的,一般就是操作 ast ;自己写的话确实不好用。用别人写好的,现在的 rust ide 支持还太差了,提示不友好。。
    dodo2012
        23
    dodo2012  
       Jul 14, 2018
    @ZSeptember vscode 现在用起来还好,v2 居然还有在用 rust 的啊,很少见,,
    janxin
        24
    janxin  
       Jul 14, 2018 via iPad
    @dodo2012 其实挺多的
    cc959798
        25
    cc959798  
    OP
       Jul 14, 2018
    @luob 这种设计可以用其他方式更改的,比如 select where join 等方法可以返回 DB 实例,可以加个类似的 Query 或者 execute 方法来返回插到的值
    cc959798
        26
    cc959798  
    OP
       Jul 14, 2018
    @bigpigeon 不是有 interface{}吗
    pubby
        27
    pubby  
       Jul 14, 2018 via Android
    你说的都还好,gorm 最坑的是查询和更新时的零值的处理
    looplj
        28
    looplj  
       Jul 14, 2018 via Android
    @pubby 我觉得设计的没问题,有什么特殊需求也可以用 hook 解决。
    xypcn
        29
    xypcn  
       Jul 14, 2018
    https://github.com/ecdiy/gpa 这是我自己实现的 orm,操作与 spring-data-jpa 差不多
    pathbox
        30
    pathbox  
       Jul 14, 2018 via iPhone
    sqlx 应该会是好的选择
    dodo2012
        31
    dodo2012  
       Jul 14, 2018
    @janxin 是不是哟,一直觉得搞 rust 的很少,特别在国内,主要是,学习曲线太,,高了
    youEclipse
        32
    youEclipse  
       Jul 14, 2018
    @bigpigeon 我用过一个生成代码的 orm 方案,叫 gorp,但是真的很不好用啊。。
    JerryCha
        33
    JerryCha  
       Jul 15, 2018
    传指针啊,这风格很 C
    glues
        34
    glues  
       Jul 15, 2018
    用 go 写业务逻辑,要死人的
    looplj
        35
    looplj  
       Jul 15, 2018 via Android
    @xypcn 你这个项目跟我的项目名一模一样。。
    looplj
        36
    looplj  
       Jul 15, 2018 via Android   ❤️ 1
    感觉大家没有 get 到 LZ 的问题啊。
    LZ 问的是为什么这些框架查询的时候需要 new 一个指针作为参数传为 find 方法,而不是像 jpa 那样作为返回值。
    其实自己尝试写一下就知道了,go 是做不到 jpa 那种的,go 没有泛型,调用的时候拿不到需要返回的类型信息,就不能在 find 方法里面实例化对象。。jpa 能做到,是因为 Java 的反射能拿到泛型特化信息,然后可以用反射实例化对象,再设置属性值的。
    cc959798
        37
    cc959798  
    OP
       Jul 15, 2018
    @ZSeptember 有道理,Go 的设计感觉还是局限性挺高的,说 Go 的开发效率和脚本语言一样快,真的不敢苟同
    cc959798
        38
    cc959798  
    OP
       Jul 15, 2018
    @ZSeptember 感觉可以不设计成使用统一 db 去查询的方式,可以类似 python 框架中 Django 中的 ORM,使用 Model 进行查询,Model 只需要继承相应的基类就可以实现这种方式,也类似于 PHP 中很多的类似的框架,比如 YII 中的 ORM
    当然传统的 ORM 几乎都是这两个设计思路
    我个人偏向于后者
    orvice
        39
    orvice  
       Jul 15, 2018
    语言特性限制吧,不能想 py/php 那么灵活。
    mritd
        40
    mritd  
       Jul 15, 2018 via iPhone
    我觉得是语言特性问题,至于传指针,我倒是觉得很好很清晰,java 把指针藏起来倒难受
    xypcn
        41
    xypcn  
       Jul 15, 2018
    @ZSeptember 你的方案不好用.我的方案,使用与 java 对比如下:

    定义 SQL

    type SqlAction struct {
    SysRoleDel func(roleId int64, roleId2 int64) (int64, error) `delete from SysRole where id=? and creator!=0 and 0=(SELECT count(*) from SysUserRole where roleId=?)`
    // insert ,delete update 都可以使用
    // select 可以返回 int,int64,string,map[string]string []int,[]......... []map[string]string object 都能反射
    }

    类似 JAVA spring-data interface 定义 SQL


    sqlAction := &SqlAction{}

    orm := GetGpa("mysql", "root:root@tcp(127.0.0.1:3306)/base-sys-user?timeout=30s&charset=utf8&parseTime=true",
    sqlAction)

    golang 没有 java 的注入之类,显示实例化,java 的实例化可以通过注入,这个可以是全局变量

    调用: sqlAction.SysRoleDel(48)

    与 java 一样方便。

    一个 orm 框架,至少要分离 sql 的调用。

    GetDb().Table("model").Find(&model, " id =? ", id) 这种设计肯定是没有理解 java 的 spring-data 接口设计,
    也是很多 java 开发者看起来比较怪异的地方


    @glues go 写业务逻辑与 java 一样方便,只是你不熟悉而已,至少需要一年以上的累积,go 的起步较高,
    它是认为开发者已经精通一门开发语言了,一个好的项目推广比较难,一般是一个公司,或是先发,累积。
    tcp
        42
    tcp  
       Jul 15, 2018 via Android
    我?
    looplj
        43
    looplj  
       Jul 15, 2018 via Android
    @xypcn 我觉得你没看明白。我的是个代码生成器,不是 ORM。生成的规则是 spring-data-jpa 的方法命名,生成的代码是基于 gorm 的,你吐槽的是 gorm 的设计。不过这也是仁者见仁的事情。Java 也有 jooq,这种框架,spring-data-jpa 也有 query DSL 也是这种形式的。
    bigpigeon
        44
    bigpigeon  
       Jul 15, 2018
    @cc959798 返回 interface{}还得强转,还得知道你想要什么类型才能强转,还不如直接传引用来的方便
    my3157
        45
    my3157  
       Jul 15, 2018
    主要还是 go 的 reflect 太弱了
    nocrush
        46
    nocrush  
       Jul 19, 2018
    laravel orm 我觉得是我用过中最好用的
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   1193 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 87ms · UTC 23:30 · PVG 07:30 · LAX 16:30 · JFK 19:30
    ♥ Do have faith in what you're doing.