go 项目中对模型映射数据库表结构的解决方案是什么? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
longmeier90
V2EX    Go 编程语言

go 项目中对模型映射数据库表结构的解决方案是什么?

  •  
  •   longmeier90 2024-10-31 16:10:54 +08:00 3766 次点击
    这是一个创建于 411 天前的主题,其中的信息可能已经有所发展或是发生改变。
    ```
    由于本人是重度 django 玩儿家,习惯 django 的那种自动 migrations 、migrate ,模型-数据库的那种迁移方式。
    现在转 go ,但是找了一下没发现,有什么好用的包可以将,struct 映射数据库(全自动),不需要手动编写 sql ,
    支持表结构一步一步修改,删除、重命名等记录。
    你们 gohper,在项目 struct->数据库当中都是怎么个管理方案。

    ```
    44 条回复    2025-09-29 20:43:47 +08:00
    ni9ht
        1
    ni9ht  
       2024-10-31 16:12:46 +08:00
    GORM ?
    securityCoding
        2
    securityCoding  
       2024-10-31 16:13:33 +08:00 via Android   1
    手动档
    Ayanokouji
        3
    Ayanokouji  
       2024-10-31 16:14:51 +08:00
    emartcn
        4
    emartcn  
       2024-10-31 16:21:09 +08:00
    object->json ,现在没哪个数据库不支持的。
    longmeier90
        5
    longmeier90  
    OP
       2024-10-31 16:24:02 +08:00
    @ni9ht 好像对表修改字段不太友好,没有深度使用
    longmeier90
        6
    longmeier90  
    OP
       2024-10-31 16:24:41 +08:00
    手动挡太慢,容易出错。团队成员水平不一样,使用工具最方便
    edisonwong
        7
    edisonwong  
       2024-10-31 16:27:37 +08:00
    gorm 里的 automigrate 。缺点在于:改已有的类型属性、或者索引改不了,比如 varchar100 ,改成 200 ,识别不了。gorm 里也有 dry run 只导出 sql
    Desdemor
        8
    Desdemor  
       2024-10-31 16:44:21 +08:00
    参考现有的工具,自己魔改啦
    lasuar
        9
    lasuar  
       2024-10-31 16:49:25 +08:00   4
    我的技术栈是 go 微服务,多年经验。

    以我个人经验哈,不要去依赖工具的 migration api ,这在做项目迁移/重构时是噩梦,并且对于日常的表维护不够透明。当我希望查一个表结构时,我需要去数据库才能查到,通过代码始终是不直观的,部分开发者为了图方便有时候会绕过代码直接修改表结构,这就使得代码中的映射成为摆设,长期以往,这其中的工程复杂度是难以想象的。!

    我项目中对于表维护的开发流程:

    1. 对于新表,在项目根目录建立 `docs/`目录,以业务为名称建立`.sql`文件,其中可以存放业务相关的一张或多张表的原始 CREATE sql 。这些文件将受到版本控制!

    2. 对于旧表的更改, 例如增删字段,首先修改文件中的 CREATE sql ,其次建立`docs/log/`子目录,在子目录中新建`yyyymmdd.sql`(时间为上线日期),其中存放用于上线日改表的 ALTER sql 。

    3. 上线时,上线人员(这个一般不会给脚本操作)手动执行 sql ,以及其他更新服务步骤。

    这样的好处:

    1. 通过`docs/`目录可以直观的看到系统中有多少业务(建了表),每个业务建表数量开发人员是基本清楚的,所以整体来说也是一目了然;
    2. 在需要做整体的表结构优化时,通过`docs/`目录可以快速浏览现有表的结构特征,并制定优化方案;
    3. 在需要迁移时,直接执行`docs`目录下的所有 sql 文件即可。
    4. 对于做了按日期/ID 拆分的表,CREATE SQL 中的表名也要加上类型的 pattern ,以便识别:`create table xxx_$yyyymm ...`;
    5. 利好开发新人;
    6. 不与开发语言绑定。极端情况下,使用其他语言重构服务时会减少很多不必要的麻烦;
    liuhan907
        10
    liuhan907  
       2024-10-31 17:01:16 +08:00
    @lasuar
    但是这些东西,在设计好的 ORM 里都有自动化工具做。敲两个命令就出来了,手动除了费事还容易出错。
    helone
        11
    helone  
       2024-10-31 17:02:25 +08:00
    entgo
    Jinnrry
        12
    Jinnrry  
       2024-10-31 17:03:32 +08:00 via iPhone
    和 Django 的 orm 比,不对,和其他任何语言的 orm 框架比,go 的 orm 框架就是一个弟弟
    lasuar
        13
    lasuar  
       2024-10-31 17:10:49 +08:00
    @liuhan907 #10 首先哈,现代化的 IDE 可以帮助你写 SQL ,其次需要维护的 SQL 都是简单的 DDL sql ,并不复杂。最后哈,基本的 sql 能力是开发人员的必备项。
    lasuar
        14
    lasuar  
       2024-10-31 17:12:37 +08:00
    @lasuar #9 纠正个小错误,是`docs/sql`目录,而不是直接的`docs/`目录。
    ninjashixuan
        15
    ninjashixuan  
       2024-10-31 17:14:33 +08:00
    老实维护 sql 版本变更吧,这玩意还是手写让人踏实。
    mogging
        16
    mogging  
       2024-10-31 17:34:37 +08:00
    GoFrame 统一管理
    liuhan907
        17
    liuhan907  
       2024-10-31 17:38:28 +08:00
    @lasuar 能自动化的东西,为何要手动维护?
    fffq
        18
    fffq  
       2024-10-31 17:39:38 +08:00
    yougg
        19
    yougg  
       2024-10-31 18:14:47 +08:00
    https://github.com/yougg/awesome-go-orms

    已主推项目从 GORM 全面切换到 sqlc 了,包含几百张表/分表查询/各种关联查询/视图/存储过程等等,上生产稳定运行运行 1 年多。
    henix
        20
    henix  
       2024-10-31 18:21:37 +08:00
    sqlc
    loading
        21
    loading  
       2024-10-31 18:25:24 +08:00
    @liuhan907 #17 生产环境还是自己背锅比较好,因为有时因为 bug ,可能就丢了列甚至表。当然,用工具生成方案是对的,但依然要人工审查一次。
    james122333
        22
    james122333  
       2024-10-31 18:40:23 +08:00 via Android
    记得没有 gorm 对类行改动好像很有问题
    我是自己根据 struct 的 tag 组成 sql 语法 从建立资料库 建立表栏位 更改表栏位语法都生成并运行
    rrfeng
        23
    rrfeng  
       2024-10-31 18:47:53 +08:00
    仓库里单独建个目录放好用来改变的 sql ,做好版本记录。
    iyaozhen
        24
    iyaozhen  
       2024-10-31 19:00:10 +08:00
    https://gorm.io/gen/
    字节内部用的这个,gorm 加强版

    可以连上数据库,生成 go 代码
    EscYezi
        25
    EscYezi  
       2024-11-01 02:16:09 +08:00 via Android
    个人感觉有个工具能对比测试库和线上库的差异比较重要。表结构个人喜欢以数据库表为核心,映射用工具生成或者手写无所谓,只要字段对的上。按这个思路的话自动迁移其实可以不用
    cooltechbs
        26
    cooltechbs  
       2024-11-01 06:22:17 +08:00 via Android
    @lasuar 同多年 Go 经验,完全同意你说的。

    另外就是新项目我基本都会给大家安利 MongoDB 和 Cassandra 这些 NoSQL ,直接避开 migration 问题。只要不是需要 transaction 的交易服务那些,NoSQL 绝对更省心(除非团队里都是 SQL 老油条)
    lasuar
        27
    lasuar  
       2024-11-01 09:10:42 +08:00 via iPhone
    @cooltechbs 大部分项目,不管是技术栈熟悉程度还是事务的方面,类 MySQL 数据库都是避不开的。

    通过我说的方式来记录表结构,还有一个优势就是我不需要去完全学会那些 orm 库的各种 tag 语法。我个人认为哈,这东西完全对开发人员是一个多余的学习成本,虽然并不复杂,但是你耐不住他语法足够多还在不断更新,完全不利好语言新人。
    而且这玩意和语言绑定,我最讨厌和什么东西绑定了,我现在的一个微服务项目没有使用任何框架,就是 go 加上 grpc ,注册发现都是直接用的 k8s 的 service ,做到足够简洁,如果有开发新人,他不需要学习额外太多东西。
    nanpu
        28
    nanpu  
       2024-11-01 09:52:49 +08:00
    gorm xorm ent
    lesismal
        29
    lesismal  
       2024-11-01 10:27:17 +08:00
    如果不用 orm, 可以试试我这个 github.com/lesismal/sqlw
    lesismal
        30
    lesismal  
       2024-11-01 10:30:21 +08:00
    @lasuar Can't agree more!
    Lychee0
        31
    Lychee0  
       2024-11-01 13:39:33 +08:00 via Android
    gorm gen
    wwhontheway
        32
    wwhontheway  
       2024-11-01 14:03:14 +08:00
    可以看看 gorm/gen or sqlc?
    hzzhzzdogee
        33
    hzzhzzdogee  
       2024-11-01 16:35:58 +08:00
    gorm gen +1
    Kauruus
        34
    Kauruus  
       2024-11-01 16:50:23 +08:00
    用 migrate 管理,但不自动执行。

    用 sqlc 生成 db 模型和查询。根据需要可以手工映射一次,隔离 db 实现。
    dododada
        35
    dododada  
       2024-11-01 17:41:11 +08:00   1
    兄弟们 sql 上线没有 dba 审核的么?
    happy32199
        36
    happy32199  
       2024-11-01 19:03:18 +08:00 via Android
    map[string]any
    hubqin
        37
    hubqin  
       2024-11-01 20:36:50 +08:00
    @fffq 我是基于这个魔改的
    gvison
        38
    gvison  
       2024-11-02 11:32:33 +08:00
    通过 sql 反向生成 go struct 映射数据库代码会更简单,连接数据库后,指定表来生成对应 gorm 的 struct 代码,https://go-sponge.com/ui/web-model
    guhuisec
        39
    guhuisec  
       2024-11-02 11:52:59 +08:00
    我用的是这个,挺好用的,每次需要哪个表就生成一下: https://github.com/xxjwxc/gormt 我的配置文件:

    https://gist.github.com/haomiao33/9482a96c0ae8367a8a134ee0e9aab7a0
    ninjashixuan
        40
    ninjashixuan  
       2024-11-02 14:37:41 +08:00
    怎么那么多人提 gorm gen 印象中这个只是 ddl -> orm model ,但是做不了 sql migrations 变更吧。
    liuhan907
        41
    liuhan907  
       2024-11-03 00:29:33 +08:00
    @loading
    反正本来就有开发环境、测试环境、预发布环境三个环境做测试,如果还能让 DDL 错误上线的话那还是毁灭吧。
    另外,不用工具什么都自己手动做,那么在不用付出学习成本的同时也意味着什么事情都要自己花时间,并且不能享有开源项目发展带来的好处。我觉得这和现在的开发理念是背道而驰的。
    linghutf
        42
    linghutf  
       2024-11-03 00:35:05 +08:00 via Android
    gentool
    dandankele
        43
    dandankele  
       79 天前
    @lasuar 有个问题想咨询下大佬。。有的 db migration 迁移工具中,提供的都是基于.sql 文件方式去做数据库表结构变更的。这样对于纯 DDL 基本是有效的,但是不知有没有这样的场景,例如在做了 DDL 之后还要做一些数据处理工作,如原有 A 字段可能因早期设计不合理,现在需要新增一个 B 字段,这是 DDL 部分,但是还需要将 A 字段中已有的数据通过脚本提取、处理、转换并更新到 B 字段上。这时数据处理的逻辑就不太好放在.sql 中编写了吧。

    我的做法都是引入第三方工具库,然后自己写脚本的,在脚本中调用库的 DDL 方法,然后再写一些额外的数据处理逻辑的。不知大佬这种抛开第三方工具独立维护的方案中,如何处理这样的需求的
    lasuar
        44
    lasuar  
       78 天前
    @dandankele 现在有了 AI ,再加上自己充足的测试用例,想要使用 **存储过程** 去完成你的数据提取/转换工作是相当简单且方便的,不需要写代码(那是额外的维护成本)。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     907 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 22:11 PVG 06:11 LAX 14:11 JFK 17:11
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86