V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
cc959798
V2EX  ›  Go 编程语言

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

  •  
  •   cc959798 · 2018-07-14 11:39:48 +08:00 · 15352 次点击
    这是一个创建于 2343 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

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

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