gen dao命令是CLI中最频繁使用、也是框架设计的工程规范能否准确落地的关键命令。该命令用于生成dao数据访问对象、do数据转化模型及entity实例数据模型Go代码文件。由于该命令的参数、选项较多,我们推荐使用配置文件来管理生成规则。

关于框架项目工程规范介绍请查看 代码分层设计 章节。

使用方式

大部分场景下,进入项目根目录执行 gf gen dao 即可。以下为命令行帮助信息。

$ gf gen dao -h
USAGE
    gf gen dao [OPTION]

OPTION
    -p, --path                  directory path for generated files
    -l, --link                  database configuration, the same as the ORM configuration of GoFrame
    -t, --tables                generate models only for given tables, multiple table names separated with ','
    -x, --tablesEx              generate models excluding given tables, multiple table names separated with ','
    -g, --group                 specifying the configuration group name of database for generated ORM instance,
                                it's not necessary and the default value is "default"
    -f, --prefix                add prefix for all table of specified link/database tables
    -r, --removePrefix          remove specified prefix of the table, multiple prefix separated with ','
    -rf, --removeFieldPrefix    remove specified prefix of the field, multiple prefix separated with ','
    -j, --jsonCase              generated json tag case for model struct, cases are as follows:
                                | Case            | Example            |
                                |---------------- |--------------------|
                                | Camel           | AnyKindOfString    |
                                | CamelLower      | anyKindOfString    | default
                                | Snake           | any_kind_of_string |
                                | SnakeScreaming  | ANY_KIND_OF_STRING |
                                | SnakeFirstUpper | rgb_code_md5       |
                                | Kebab           | any-kind-of-string |
                                | KebabScreaming  | ANY-KIND-OF-STRING |
    -i, --importPrefix          custom import prefix for generated go files
    -d, --daoPath               directory path for storing generated dao files under path
    -o, --doPath                directory path for storing generated do files under path
    -e, --entityPath            directory path for storing generated entity files under path
    -t1, --tplDaoIndexPath      template file path for dao index file
    -t2, --tplDaoInternalPath   template file path for dao internal file
    -t3, --tplDaoDoPath         template file path for dao do file
    -t4, --tplDaoEntityPath     template file path for dao entity file
    -s, --stdTime               use time.Time from stdlib instead of gtime.Time for generated time/date fields of tables
    -w, --withTime              add created time for auto produced go files
    -n, --gJsonSupport          use gJsonSupport to use *gjson.Json instead of string for generated json fields of
                                tables
    -v, --overwriteDao          overwrite all dao files both inside/outside internal folder
    -c, --descriptionTag        add comment to description tag for each field
    -k, --noJsonTag             no json tag will be added for each field
    -m, --noModelComment        no model comment will be added for each field
    -a, --clear                 delete all generated go files that do not exist in database
    -y, --typeMapping           custom local type mapping for generated struct attributes relevant to fields of table
    -h, --help                  more information about this command

EXAMPLE
    gf gen dao
    gf gen dao -l "mysql:root:12345678@tcp(127.0.0.1:3306)/test"
    gf gen dao -p ./model -g user-center -t user,user_detail,user_login
    gf gen dao -r user_

CONFIGURATION SUPPORT
    Options are also supported by configuration file.
    It's suggested using configuration file instead of command line arguments making producing.
    The configuration node name is "gfcli.gen.dao", which also supports multiple databases, for example(config.yaml):
    gfcli:
      gen:
        dao:
        - link:     "mysql:root:12345678@tcp(127.0.0.1:3306)/test"
          tables:   "order,products"
          jsonCase: "CamelLower"
        - link:   "mysql:root:12345678@tcp(127.0.0.1:3306)/primary"
          path:   "./my-app"
          prefix: "primary_"
          tables: "user, userDetail"
          typeMapping:
            decimal:
              type:   decimal.Decimal
              import: github.com/shopspring/decimal
            numeric:
              type: string

如果使用框架推荐的项目工程脚手架,并且系统安装了make工具,也可以使用make dao快捷指令。

配置示例

/hack/config.yaml

gfcli:
  gen:
    dao:
    - link:     "mysql:root:12345678@tcp(127.0.0.1:3306)/test"
      tables:   "order,products"
      jsonCase: "CamelLower"

    - link:   "mysql:root:12345678@tcp(127.0.0.1:3306)/primary"
      path:   "./my-app"
      prefix: "primary_"
      tables: "user, userDetail"

	# sqlite需要自行编译带sqlite驱动的gf,下载库代码后修改路径文件(gf\cmd\gf\internal\cmd\cmd_gen_dao.go)的import包,取消注释即可。sqlite驱动依赖了gcc
	- link: "sqlite:./file.db"

参数说明

名称默认值含义示例
gfcli.gen.dao
dao代码生成配置项,可以有多个配置项构成数组,支持多个数据库生成。不同的数据库可以设置不同的生成规则,例如可以生成到不同的位置或者文件。-

link

必须参数


分为两部分,第一部分表示你连接的数据库类型mysql, postgresql等, 第二部分就是连接数据库的dsn信息。具体请参考 ORM使用配置 章节。

-

pathinternal

生成daomodel文件的存储目录地址。

./app
groupdefault

在数据库配置中的数据库分组名称。只能配置一个名称。数据库在配置文件中的分组名称往往确定之后便不再修改。

default

order

user

prefix
生成数据库对象及文件的前缀,以便区分不同数据库或者不同数据库中的相同表名,防止数据表同名覆盖。

order_

user_

removePrefix
删除数据表的指定前缀名称。多个前缀以,号分隔。gf_
removeFieldPrefix
删除字段名称的指定前缀名称。多个前缀以,号分隔。f_
tables
指定当前数据库中需要执行代码生成的数据表。如果为空,表示数据库的所有表都会生成。user, user_detail
tablesEx
Tables Excluding,指定当前数据库中需要排除代码生成的数据表。product, order
jsonCaseCamelLower

指定model中生成的数据实体对象中json标签名称规则,参数不区分大小写。参数可选为:CamelCamelLowerSnakeSnakeScreamingSnakeFirstUpperKebabKebabScreaming。具体介绍请参考命名行帮助示例。

Snake
stdTimefalse

当数据表字段类型为时间类型时,代码生成的属性类型使用标准库的time.Time而不是框架的*gtime.Time类型。

true
withTimefalse为每个自动生成的代码文件增加生成时间注释
gJsonSupportfalse

当数据表字段类型为JSON类型时,代码生成的属性类型使用*gjson.Json类型。

true
overwriteDaofalse每次生成dao代码时是否重新生成覆盖dao/internal目录外层的文件。注意dao/internal目录外层的文件可能由开发者自定义扩展了功能,覆盖可能会产生风险。true
importPrefix通过go.mod自动检测

用于指定生成Go文件的import路径前缀。特别是针对于不是在项目根目录下使用gen dao命令,或者想要将代码文件生成到自定义的其他目录,这个时候配置该参数十分必要。


github.com/gogf/gf
descriptionTagfalse

用于指定是否为数据模型结构体属性增加desription的标签,内容为对应的数据表字段注释。

true
noJsonTagfalse生成的数据模型中,字段不带有json标签
noModelCommentfalse

用于指定是否关闭数据模型结构体属性的注释自动生成,内容为数据表对应字段的注释。

true
clearfalse自动删除数据库中不存在对应数据表的本地dao/do/entity代码文件。请谨慎使用该参数!
typeMappingdecimal:
  type: float64
money:
  type: float64
numeric:
  type: float64
smallmoney:
  type: float64

从版本v2.5开始支持。

用于自定义数据表字段类型到生成的Go文件中对应属性类型映射。该配置支持通过import配置引入第三方包,例如:

decimal:
  type:   decimal.Decimal
  import: github.com/shopspring/decimal


daoPathdao代码生成的DAO文件存放目录
doPathmodel/do代码生成DO文件存放目录
entityPathmodel/entity代码生成的Entity文件存放目录
tplDaoIndexPath
自定义DAO Index代码生成模板文件路径,使用该参数请参考源码
tplDaoInternalPath
自定义DAO Internal代码生成模板文件路径,使用该参数请参考源码
tplDaoDoPath
自定义DO代码生成模板文件路径,使用该参数请参考源码
tplDaoEntityPath
自定义Entity代码生成模板文件路径,使用该参数请参考源码

使用示例

仓库地址:https://github.com/gogf/focus-single

1、以下3个目录的文件由dao命令生成:

路径说明详细介绍
/internal/dao数据操作对象通过对象方式访问底层数据源,底层基于ORM组件实现。往往需要结合entitydo通用使用。该目录下的文件开发者可扩展修改,但是往往没这种必要。
/internal/model/do数据转换模型

数据转换模型用于业务模型到数据模型的转换,由工具维护,用户不能修改。工具每次生成代码文件将会覆盖该目录。关于do文件的介绍请参考:

/internal/model/entity数据模型

数据模型由工具维护,用户不能修改。工具每次生成代码文件将会覆盖该目录。

2、model中的模型分为两类:数据模型业务模型

数据模型:通过CLI工具自动生成 model/entity 目录文件,数据库的数据表都会生成到该目录下,这个目录下的文件对应的模型为数据模型。数据模型即与数据表一一对应的数据结构,开发者往往不需要去修改并且也不应该去修改,数据模型只有在数据表结构变更时通过CLI工具自动更新。数据模型由CLI工具生成及统一维护。

业务模型:业务模型即是与业务相关的数据结构,按需定义,例如service的输入输出数据结构定义、内部的一些数据结构定义等。业务模型由开发者根据业务需要自行定义维护,定义到model目录下。

3、dao中的文件按照数据表名称进行命名,一个数据表一个文件及其一个对应的DAO对象。操作数据表即是通过DAO对象以及相关操作方法实现。dao操作采用规范化设计,必须传递ctx参数,并在生成的代码中必须通过Ctx或者Transaction方法创建对象来链式操作数据表。

注意事项

需要手动编译的数据库类型

gen dao命令涉及到数据访问相关代码生成时,默认支持常用的若干类型数据库。如果需要Oracle数据库类型支持,需要开发者自己修改源码文件后自行本地手动编译生成CLI工具随后安装,因为这两个数据库的驱动需要CGO支持,无法预编译生成给大家直接使用。

关于bool类型对应的数据表字段

由于大部分数据库类型都没有bool类型的数据表字段类型,我们推荐使用bit(1)来代替bool类型。gen dao命令会自动识别bit(1)数据表字段并生成bool类型的属性。此外,我们不推荐使用tinyint(1)作为bool类型。

例如,表字段:

生成的属性:




Content Menu

  • No labels

168 Comments


  1. gf-cli如果是低于此版本使用gf gen dao生成的代码,更新到图片上的版本,出现生成的版本,需要同时删除dao下和dao/internal/下对应的文件,新版不是指针版本了。

    1. 去掉指针设计是因为对象访问安全的缘故,具体请参考章节:对象封装设计(更新中)

      1. 但是去掉了指针给我带来了一点困扰,

        mo := dao.SysRoleMenu
        mo.Where(mo.Columns.RoleId+"=?", cs.Id).All()
        all, err := mo.All()

        这样写法就没法叠加where的条件了,应该如何解决.我试过mo := &dao.SysRoleMenu可以解决,但是我不知道这样写是不是又用回了指针,正确的做法应该是怎样的.

        1. 同样的方法,应该是一样的

        2. 你呀!你的dao.SysRoleMenu相当于只是一个方法封装对象,你的各个model方法会返回一个新的链式操作对象,保存返回的对象用以后续的ORM操作。例如:

          // 带条件查询的返回结果
          allThatHasCondition, err := dao.SysRoleMenu.Where(mo.Columns.RoleId, cs.Id).All()
          // 不带条件查询的返回结果
          allThatHasNoCondition, err := dao.SysRoleMenu.All()
          1. 我又研究了一遍示例项目搞懂了,感谢解答.目前对全局变量有点懵懂,看来得加深理解.

            1. foucs-single的示例项目不是最新的吧  我看dao层还是在internal层, 最新生成的应该是在service层

  2. 各位大佬。分表的场景下怎么合理使用gen代码生成。比如订单表每月生成一个,表名称类似于order_202001、order_202002、order_202003

    1. 目前gen dao命令不支持识别分表,可以加个正则匹配匹配的配置项来做识别,欢迎提PR。

  3. 请问下 目前支持 mongoDB 么?支持的话有没有代码生成操作示例?

    1. 暂不支持,不过根据接口设计可以很方便支持的,感兴趣可以参与贡献社区模块来对接,驱动开发请参考:ORM接口开发-驱动开发

  4. 1.16下生成的dao似乎与1.15下不一样了吧?不会直接返回表结构相应的对象了?而是改成map返回了么?针对这块,有没有一个专门的介绍帖子?

    1. cli只是开发辅助工具,与框架组件本身关系不大。从cli v1.16版本开始简化了生成的代码内容,具体看下发布说明以及生成的代码。

      1. 1.15过来,一开始对1.16还是很多不适应。调整了大量代码后,现在还是可以用了。不过,从开发效率上来说,还是比较喜欢1.15的那种风格。现在1.16这种风格,反倒比较像是使用PHP了。感觉这块把字段给弱化后,在编写代码时,为了要写一个预定义的字段,要写老长一段代码,我一般是这样:dao.xxx.Columns.Fieldxxx  要写4级才行。这块看看能不能给想办法简化下(或者是我还不会用^_^)。不然还不如直接写 fieldxxx方便。

        旧代码我现在都调整为了StructStructs。这样也可以用起来了。

        1. 估计你用过gf2.0就是一种全新的感受 了.我是蒙圈中

  5. jsonCase 能不能直接使用数据库的字段名

  6. 不然重构业务的时候比较复杂

    1. 设置为空即可。

  7. 在使用go-zero框架时, 把它的数据库操作换成了dao, 方便了很多。

    但是二者对比, 希望增加一个和go-zero一样的功能,即 mysql+redis 自动生成: 生成带redis cache或者不带redis cache的代码逻辑。

    gf gen dao -l mysqlxxxxxx -r redis:xxxxxx

    1. 缓存的逻辑由业务控制,使用Cache方法即可,使用简便,具体请查看章节:ORM链式操作-查询缓存

  8. gf gen dao -l后面参数,mysql密码中如果有带感叹号会报错,提示event not found

    1. 各种参数都写在config.toml配置文件里,然后只执行gf gen dao 命令

  9. 请问一下 删除数据表的指定前缀名称 removePrefix 这个参数可以多个吗

    1. 可以,看下help说明。

  10. 发现一个问题 当有多个  gfcli.gen.dao 配置时 gf gen dao 生成model.go 里面只有最后一个配置的表模型 

    [[gfcli.gen.dao]]
    link = ""
    group = ""
    jsonCase = ""
    tables = ""
    descriptionTag = true
    noModelComment = true

    配置了这几个参数


    1. 试试最新的gf-climaster分支。

      1. GoFrame CLI Tool v1.17.0, https://goframe.org 
        GoFrame Version: v1.16.1 in current go.mod

        同样出现

  11. 大佬, 请问下自己写的驱动, gf gen dao 的时候无法初始化怎么办?

    ERRO gdb.Instance Error: cannot find database driver for specified database type "clickhouse", did you misspell type name "clickhouse" or forget importing the database driver? 
    
    Error: database initialization failed
    1. 这种情况你需要自行修改CLI源码以增加对第三方数据库的支持,import一下就可以了。

      1. 谢谢, 之前发现前面一片文档里有说明, 已经解决了

  12. -c参数怎么没效果呀?我执行 gf gen dao -c config-test.toml  还是用的config.toml

  13. 现在的gf-demos项目, 在这个项目里面用gf工具生成出来的dao 和 model 文件有些重复了, 可否修改下 gf-demos项目? 

  14. 指定了path之后不能根据path的目录结构自动生成目录,需要手动建立好之后才可以生成到指定目录,希望能根据path配置的路径自动生成目录.

    还有就是dao和model的名称是定死的,希望能配置别名,生成的时候就不是必须用dao和model这两个名字了,不然有多个数据库时使用就很麻烦,因为同名了

  15. Cli 升级工具应该是发一个大的公告, 我刚刚生成一下傻眼了.怎么回事不一样.

    GoFrame CLI Tool v1.17.0, https://goframe.org 
    GoFrame Version: v1.16.6 in current go.mod 
    CLI Installed At: /usr/local/bin/gf 
    CLI Built Detail:
      Go Version:  go1.16.3
      GF Version:  v1.16.4
      Git Commit:  971ed46f0b9d4dfebd1907cd3ed851cf9e1a5503
      Build Time:  2021-08-10 10:22:59 

    才发现上面写到v1.17 会进行简化.难搞喔. 

    1. cli工具似乎是一直是最新版本。能不升还是不要升的好。现在最新版本与1.16.6差异很大。

      1. 1.17 需要传一个上下文

  16. GoFrame CLI Tool v1.17.0,  

    -c --config无效
    gf gen dao -c ./conf/db2model.toml -path ./src/model
    

     只能默认调用项目目录下的 config.toml    


  17. descriptionTag 和 noModelComment  设置的都是true,但生成的model.go 中的注释是空的,连的pgsql,数据库中是有设注释的:pic2.png (939×491) (aucheer.tech)  pic1.png (930×423) (aucheer.tech)

    1. 文档内容都是最新版,需要自己编译master分支

      1. 好的,谢谢

  18. 表名都是加了s的复数,就像Laravel一样,生成的model和dao可怎么把s去了?

    强迫症晚期。

  19. 能否在dao层自动添加一些单表的简单增删改查呢?


  20. 你安装最新的gf-cli试试,如何安装请查看gf-cli仓库README

  21. 2.0 生成dao的时候 oracle数据库 不会读取字段说明信息生成到代码中

  22. 2.0 mssql数据库中字段类型为Money 生成的entity json的类型是string,  这是有参数控制吗? 类型错误,会导致生成的接口文档也是错误的 

  23. gfcli.gen.dao 部分的link配置,是不是和 db 部分的配置重复了?可以只配置一处吗?

    1. link可能一样,但多数情况是不同的,也有其它配置信息的差异,也有不同环境的情况,为避免不必要的影响,所以不应该一样。

    2. database的配置是业务配置,这里的gfcli配置是工具配置。

      也就是说,业务配置是线上运行需要的(一般在manifest/config目录下),而gfcli配置只是开发阶段需要的(一般在hack目录下)。

      两个配置文件应该需要分开,并且我们的框架支持如此,可以参考示例项目。

      1. 收到,明了了,感谢回复

  24. gen自动把mysql里的boolean转化成了int, 有办法对这个行为进行修改或者定制吗?

    1. 应该mysql里面就是int类型,你可以把建表sql提个issue我们一起看看。

  25. 这里是不是可以增加一个配置,json是否可以格式化显示float类型。

    1. 字段如果是json类型,可以生成string/*gjson.Json类型,如果是*gjson.Json类型的话从v2.1版本开始解决了浮点数精度问题。

      1. 那太好了。老大威武

  26. tables, tablesEx能不能支持类似正则,比如sys_*,只想对某些前缀的表进行gen

    1. 目前不支持正则,写个多个来过滤吧。


  27. hmy

    // =================================================================================
    // Code generated by GoFrame CLI tool. DO NOT EDIT. Created at 2022-05-01 20:41:03
    // =================================================================================


    Created at 2022-05-01 20:41:03  这个可以配置隐藏掉吗


    1. WithTime参数可以去掉

  28. 请问最新的gf gen dao路径是不是有变化

    1、以下3个目录的文件由dao命令生成:
    
    /internal/model/entity	数据模型	
    数据模型由工具维护,用户不能修改。
    
    工具每次生成代码文件将会覆盖该目录。
    
    /internal/service/internal/do	数据转换模型	
    数据转换模型用于业务模型到数据模型的转换,由工具维护,用户不能修改。
    
    工具每次生成代码文件将会覆盖该目录。
    
    /internal/service/internal/dao	数据操作对象	通过对象方式访问底层数据源,底层基于ORM组件实现。往往需要结合entity和do通用使用。该目录下的文件开发者可扩展修改,但是往往没这种必要。
    我本地生成的
    (base) [wq@feranMacBook:moorsync (master)]$ gf gen dao -v
    2022-05-13 22:43:58.316 [DEBU] {10422f8448b1ee16033d007cf156216e} [ 12 ms] [default] [rows:1  ] SHOW TABLES
    2022-05-13 22:43:58.321 [DEBU] {2894f78348b1ee16023d007c0ac9b9c8} [  5 ms] [default] [rows:16 ] SHOW FULL COLUMNS FROM `work_order`
    generated: internal/dao/work_order.go
    generated: internal/dao/internal/work_order.go
    generated: internal/model/do/work_order.go
    generated: internal/model/entity/work_order.go
    done!
    (base) [wq@feranMacBook:moorsync (master)]$ gf -v
    GoFrame CLI Tool v2.0.6, https://goframe.org
    GoFrame Version: cannot find goframe requirement in go.mod
    CLI Installed At: /Users/wq/go/bin/gf
    Current is a custom installed version, no installation information.
    1. 这里 https://github.com/gogf/gf/releases 下载已经编译好的二进制,自己编译的我试了下目录结构确实变了

  29. hh

    gf gen dao无法生成文件,报驱动找不到。我的gf版本如下。

    λ gf -v
    GoFrame CLI Tool v2.1.0-rc, https://goframe.org
    GoFrame Version: v2.1.0-rc in current go.mod
    CLI Installed At: D:\Program Files\Go\bin\gf.exe
    CLI Built Detail:
      Go Version:  go1.17.9
      GF Version:  v2.1.0-rc
      Git Commit:  2022-05-17 16:43:10 62d91438f2377debe7ead16ab058d9dd707744ad
      Build Time:  2022-05-17 16:41:42


    报错如下:

    λ gf gen dao
    cannot find database driver for specified database type "mysql", did you misspell type name "mysql" or forget importing the database driver? possible reference: https://github.com/gogf/gf/tree/master/contrib/drivers
    1. cannot find database driver for specified database type "mysql", did you misspell type name "mysql" or forget importing the database driver? possible reference: https://github.com/gogf/gf/tree/master/contrib/drivers

    按照之前的教程,在main.go上手动引入了_ "github.com/gogf/gf/contrib/drivers/mysql/v2",还是不行。求帮助

    1. 我昨天遇到这个问题了。猜想应该是这个版本的cli-tool未引入mysql。

      解决1:拉取,自行修改CLI源码,自己编译使用;

      解决2:使用旧版本,比如我目前版本:

      GoFrame CLI Tool v2.0.6, https://goframe.org
      GoFrame Version: v2.0.6 in current go.mod

      1. hh

        多谢,因为新版本里有解决with可以查找倒嵌套的结构体里的字段的问题。我尝试了解决1,还是没有解决我的问题,只好回退到了2.0.6。

    2. v2.1.0-rc3 版本好像解决了。可以试试

  30. v2.1.0-rc3版本。gen dao没有生成service。默认gen service需要logic目录,新建后执行gen service done!后logic目录没有任何东西,请问是要废弃service生成吗?还是我用法不对

    1. 解决了吗,我和你一样的问题

      1. 没有,1.16版本发现yaml配置tablesEx,命令行-c参数,-e参数,多个group时候-g参数都不好用,等等问题都有,先放弃研究了...

  31. linux系统:

    执行gf gen service生成报错


    haima@haima-PC:/media/haima/34E401CC64DD0E282/site/go/src/gfoframe/df-web-demo1/myapp$ gf version
    GoFrame CLI Tool v2.1.0-rc4, https://goframe.org
    GoFrame Version: cannot find goframe requirement in go.mod
    CLI Installed At: /usr/local/bin/gf
    CLI Built Detail:
      Go Version:  go1.17.10
      GF Version:  v2.1.0-rc4
      Git Commit:  2022-06-01 16:36:40 0639becccc486fda179b81e7a685f67c91b173a4
      Build Time:  2022-06-01 16:34:52
    haima@haima-PC:/media/haima/34E401CC64DD0E282/site/go/src/gfoframe/df-web-demo1/myapp$ gf gen service
    source folder path "internal/logic" does not exist


    手动新建internal/logic后,再次执行不生成文件

    haima@haima-PC:/media/haima/34E401CC64DD0E282/site/go/src/gfoframe/df-web-demo1/myapp$ gf gen service
    done!

    haima@haima-PC:/media/haima/34E401CC64DD0E282/site/go/src/gfoframe/df-web-demo1/myapp$ ll internal/logic/
    总用量 0

    1. 我发完贴才发现,我们的情况一样哦.我是win11系统,也是创建了logic目录后,无法生成service目录文件

  32. 使用最新的gf命令行工具,按照接口维护-gen service章节的gen service命令执行后,没有生成services目录,只是提示logic要创建.我创建了logic后,该如何操作才能生成service目录中的文件呢?还有logic目录的文件该如何书写呢?

    1. 建议等正式发布再使用

  33. 新版本没有指定目录的参数了  -c config.yaml 不起作用, mysql的链接可以生成,pgsql的链接提示 database initialization failed,感觉对pgsql支持相当不友好,以前的gf生成的pgsql的实体都没有字段描述

    1. func doNewByNode(node ConfigNode, group string) (db DB, err error) {
      c := &Core

      Unknown macro: { group}

      if v, ok := driverMap[node.Type]; ok {
      c.db, err = v.New(c, &node)
      if err != nil

      Unknown macro: { return nil, err }

      return c.db, nil
      }
      return nil, gerror.NewCodef(
      gcode.CodeInvalidConfiguration,
      `cannot find database driver for specified database type "%s", did you misspell type name "%s" or forget importing the database driver?`,
      node.Type, node.Type,
      )
      }

      driverMap 测试只有mysql,如何支持pgsql

    2. 请问v2啥时候支持pgsql

      gf/v2 只支持

      // driverMap manages all custom registered driver.
      driverMap = map[string]Driver{
      DriverNameMysql: &DriverMysql{},
      }
      gf/v1 支持
      // driverMap manages all custom registered driver.
      driverMap = map[string]Driver{
      "mysql": &DriverMysql{},
      "mssql": &DriverMssql{},
      "pgsql": &DriverPgsql{},
      "oracle": &DriverOracle{},
      "sqlite": &DriverSqlite{},
      }

      1. 我也是遇到了同样的问题,我是需要sqlite不成功

        根据官方的提示修改注释编译后不成功:

        cannot find database driver for specified database type "sqlite", did you misspell type name "sqlite" or forget importing the database driver?

        应该是和我设置了  CGO_ENABLED=0 有关系。

        1. sqlite要自己编译

          下载gf代码再引入sqlite的驱动gf/contrib/drivers at master · gogf/gf (github.com) 再编译

          1. 文件路径在 gf\cmd\gf\internal\cmd\cmd_gen_dao.go

            1. 我拉错脚本了,拉了gf-cli的代码,应该是编译  gf\cmd\gf 在这里引用sqlite驱动,谢谢

              1. 是的,现在gf-cli在gf主库里面了

                1. windows下会有错误,已经从wsl里搞定了。谢谢

  34. 18lkdev 文档改重复了,你看看是不是操作失误。

    1. 本来改了的,后来想了想又撤回了. 因为不确定你们版本更新不更新, 因为要改好几处文档升级了2.1 那么2.0.6的就会有问题

  35. 总结:
    1、每次执行 gf gen dao 命令,除了 internal/service/internal/dao/internal/ 目录下的文件,都会重新生成,因为这些文件由工具维护,所以开发者尽量不去修改这些文件。

    2、开发者可在 internal/service/internal/dao/internal/ 目录下进行扩展修改,但是往往没这种必要。

    3、如果需要重新生成所有的文件,执行命令:gf gen dao -o

    4、关于 jsonCase 配置项说明

     | Case                             | Example                       |
     |------------------------- |--------------------------|
     | Camel                           | AnyKindOfString         |
     | CamelLower                 | anyKindOfString          | default
     | Snake                           | any_kind_of_string       |
     | SnakeScreaming          | ANY_KIND_OF_STRING |
     | SnakeFirstUpper          | rgb_code_md5              |
     | Kebab                          | any-kind-of-string        |
     | KebabScreaming         | ANY-KIND-OF-STRING |

     | 设置为,或其他值    | 变量名和表字段名会保持一致 |

  36. 大佬们请问有没有办法把生成的结构体的s给去了,比如表名Users对应一个User结构体这样子= =

  37. 最新版v2.x的gf gen dao有bug,gJsonSupport参数设置成了true,输出的entity中json字段还是string类型的。试验数据库mysql 5.7。

    跟踪goframe cli代码发现,问题出在gf\database\gdb\gdb_func_structure.go文件中的   CheckValueForLocalType 函数:该函数没有定义json类型的处理分支,最终默认返回了typeString,导致生成的entity中json字段类型变成了string。

    如下所示,在CheckValueForLocalType函数中添加json处理分支,搞定!

    // 新加json处理分支
    case
    strings.Contains(typeName, "json"):
    return "json", nil

    default:
    return typeString, nil



    1. 确实有这个问题,而且还有一个问题数据库字段设置BIT(1)类型,生成的文件里字段属性不是bool类型而是 int  

      1. 我在GF v2.1.2上也有同样的问题,就是bit(1)生成的是int类型,而不是文档里说的bool

  38. v2.1.3版本的gf gen dao生成数据库字段类型好像和以前不一样了,uint变成了int类型。这个算bug么?还是特意的修改?

  39. v2.1.2版本,gf gen dao生成的文件目录为:

    /internal/dao/

    /internal/dao/internal

    /internal/model/do

    /internal/model/entity


    并非gf init自动创建工程的目录
    /internal/service/internal/dao/

    /internal/service/internal/dao/internal 

    /internal/service/internal/do

    /internal/model/entity

  40. 现在的生成Dao如果要重新配置数据库配置,应该从哪里着手?比如,原来是从config.toml default中读取的数据库配置,现在我想从代码中传入(比如要把部分dao修改配置为第二个数据库信息)。需要怎么配置才能让dao均生效?

    1. 配置中添加第二个数据库配置,配置group的字段。生成不会影响dao部分,dao/internal中的代码,Group会对应配置

      以下是YAML的示例:
      配置示例
      gfcli:
        gen:
          dao:
            - link: "mysql:user:password@tcp(127.0.0.1:3306)/db1" 
      
            - link: "mysql:user:password@tcp(127.0.0.1:3306)/db2"
              group: "db2"

      db1没配置group,则默认default

      db2配置了group,dao/internal中的Group会被赋值"db2"

      1. 我是想不使用配置文件的情况下修改某一批dao的数据库配置。

        我是想实现这样的:

        1. 本地无配置文件,将初始配置全放于SQL文件中,第一次启动时,导入sqlite中(sqlite的连接信息硬编码到代码中,不变)。
        2. 由于本地一开始有了一个sqlite,这时就可以启动WEB页面进行真实数据库的配置了。这个时候可以配置MYSQL等(当然也可以依然使用sqlite)。
        3. 将配置的MYSQL连接信息存于sqlite中,即最初的sqlite则是我的配置存放的地方。
        4. 这个时候需要访问mysql的dao就需要从sqlite中读取配置信息来初始化db对象。就是不知道dao有没有提供这种自定义的db初始化的处理方式

        我阅读代码,是发现dao的初始化是在框架中完成。不过我们的数据库配置都是默认从配置文件中读取的。我若想从内存中传到数据库配置应该怎么做呢?我想到的是,是不是可以实现一个自定义的cfg类。来替换掉原来的gcfg

        1. 可能尝试clone gf的源码,修改用于gen dao的template部分,把internal模板部分,新增自定义接口,放出来会比你实现自定义cfg来的轻松一些...

          goframe框架服务层很多都围绕默认的cfg来运作的。

          自己改动,内容有点多了吧。

          此处还是郭大郭强 ,来解答吧。

          1. 我看2.x里有cfg的接口实现,现在在尝试这一块。看看使用sqlite去实现下这个接口能不能行。只是由于gdb.New依赖于gcfg,所以不能在自己实现的接口中去使用gdb.New,只能使用原生db操作了。

  41. 求助:关于bool类型对应的数据表字段,我数据库创建了status字段为BIT类型:

    CREATE TABLE IF NOT EXISTS `sys_config` (
      `id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
      `status` bit(1) NOT NULL DEFAULT 0 COMMENT '0-前端不显示,1-前端显示'
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='数据表';

    命令工具执行:gf gen dao 后生成的文件字段属性并不是bool 类型的值,反而是int类型,如下:

    type SysConfig struct {

           Status int `json:"status" description:"0-前端不显示,1-前端显示"` // 0-前端不显示,1-前端显示

    }


    无法自动识别并生成 bool 类型

    1. 是mssql数据库吗?

      升级最新的gf试试

  42. asb

    您好,我是Go的新手,最近想以GoFrame來入手,目前想執行focus-single來學習,想釐清一下database的概念,gf gen dao的時候會同時建立資料庫裡的table的嗎?還是單純的建立go file而已呢?
    以前我是用Laravel,在Laravel的概念是建好model,就可以用migration的方式自動創建好資料庫的table,在goframe裡面有一樣的概念嗎?
    因為我run focus-single的時候make dao,看到done!的提示,但資料庫依舊沒有任何的table,因此提問,謝謝!

    1. 不会创建表信息.Focus聚焦社区这个是使用教程,参照示例创建数据库.gf gen dao是单向的将表映射成实体结构文件.

  43. 您好,我是一名刚刚接触go项目的新手,请问一下如果我有联表查询的需求该如何在dao层操作呢?比如查询user表,需要用user表中的menu_id去查询相应的menu一起返回。我以前的操作是新建一个包含了所需的user、menu的字段的结构体,然后在进行联表查询。但是在这个dao层中的工具会在每次生成模型的时候覆盖掉entity层的结构体,请问我该将新建的结构体保存在哪里,或者是该采用哪一种新的方法来解决这个问题?谢谢!

    1. 复制entity并对复制出来的对象增加关联成员字段.

      1. 非常感谢!

  44. GoFrame CLI Tool v2.2.0,postgresql数据库,数据字段类型是bigint,gen dao 生成的代码类型变成int了,这里应该是int64吧?还有视图都没有自动生成代码。

  45. GoFrame CLI Tool v2.2.1, https://goframe.org
    GoFrame Version: cannot find goframe requirement in go.mod


    配置文件/manifest/config/config..yaml

    配置了database

    database:
    logger:
    level: "all"
    stdout: true
    default:
    link: "pgsql:postgres:123456@tcp(127.0.0.1:5432)/postgres"

    但是执行gf gen dao的时候报错找不到database node

    [FATA] {243b0174dfeb2517ee8e4d3b33ad7a49} database initialization failed: configuration missing for database node "database"


    1. Jay

      在hack目录下的config中进行db配置

      1. 感谢,已解决~


  46. 请问有办法指定 gfcli 的配置文件的位置吗,上面说的 -c 好像不起作用,它还是从默认的几个路径去读取配置。

    1. 默认从项目根目录获取,再是hack目录。

  47. kw

    新版本有问题:

    CLI Built Detail:                                                          
      Go Version:  go1.17.13                                                   
      GF Version:  v2.2.4                                                      
      Git Commit:  2022-11-16 10:10:59 14d2d747f6f2a03c17b0c4dec7a3d103a52ad382
      Build Time:  2022-11-16 10:30:08      

    错误信息:

    fetching tables fields failed for table "表A": dial tcp :0: connectex: The requested address is not valid in its context., SHOW FULL COLUMNS FROM `表A`
    1. dial tcp :0: connectex: The requested address is not valid in its context., SHOW FULL COLUMNS FROM `表A`
       1).  github.com/gogf/gf/v2/database/gdb.(*Core).DoCommit
            /home/runner/work/gf/gf/database/gdb/gdb_core_underlying.go:281
       2).  github.com/gogf/gf/v2/database/gdb.(*Core).DoQuery
            /home/runner/work/gf/gf/database/gdb/gdb_core_underlying.go:74
       3).  github.com/gogf/gf/v2/database/gdb.(*Core).DoSelect
            /home/runner/work/gf/gf/database/gdb/gdb_core.go:144
       4).  github.com/gogf/gf/contrib/drivers/mysql/v2.(*Driver).TableFields
            /home/runner/work/gf/gf/contrib/drivers/mysql/mysql.go:148
       5).  github.com/gogf/gf/v2/database/gdb.(*DriverWrapperDB).TableFields.func1
            /home/runner/work/gf/gf/database/gdb/gdb_driver_wrapper_db.go:80
       6).  github.com/gogf/gf/v2/container/gmap.(*StrAnyMap).doSetWithLockCheck
            /home/runner/work/gf/gf/container/gmap/gmap_hash_str_any_map.go:217
       7).  github.com/gogf/gf/v2/container/gmap.(*StrAnyMap).GetOrSetFuncLock
            /home/runner/work/gf/gf/container/gmap/gmap_hash_str_any_map.go:254
            /home/runner/work/gf/gf/os/gcmd/gcmd_command_run.go:152
       17). github.com/gogf/gf/v2/os/gcmd.(*Command).RunWithValueError
            /home/runner/work/gf/gf/os/gcmd/gcmd_command_run.go:91
       18). github.com/gogf/gf/v2/os/gcmd.(*Command).RunWithValue
            /home/runner/work/gf/gf/os/gcmd/gcmd_command_run.go:41
       19). github.com/gogf/gf/v2/os/gcmd.(*Command).Run
            /home/runner/work/gf/gf/os/gcmd/gcmd_command_run.go:35
       20). main.main
            /home/runner/work/gf/gf/cmd/gf/main.go:72
       21). runtime.main
            /opt/hostedtoolcache/go/1.17.13/x64/src/runtime/proc.go:255
       22). runtime.goexit
            /opt/hostedtoolcache/go/1.17.13/x64/src/runtime/asm_amd64.s:1581



    验证:

      Go Version:  go1.17.11
      GF Version:  v2.1.2
      Git Commit:  2022-07-12 14:08:56 d2c1d773db69c0afd8209cb7344f6f2ae4fe081c
      Build Time:  2022-07-12 14:10:16

    此版本无问题

    1. gfcli 2.2.5  我这边也遇到这个问题了, 数据库地址之前是不用加端口的, 现在要加上就好了

      1. 连接clickhouse生成代码,请问这个问题怎解解决呀,端口号也加了。mysql是可以正常生成的

        CLI Built Detail:
          Go Version:  go1.19.2
          GF Version:  v2.2.5
          Git Commit:  none
          Build Time:  2022-11-29 16:16:54

        fetching tables fields failed for table "*****": [handshake] unexpected packet [72] from server, select name,position,default_expression,comment,type,is_in_partition_key,is_in
        _sorting_key,is_in_primary_key,is_in_sampling_key from `system`.columns c where `table` = '******'
        1. [handshake] unexpected packet [72] from server, select name,position,default_expression,comment,type,is_in_partition_key,is_in_sorting_key,is_in_primary_key,is_in_sampling_key from 
        `system`.columns c where `table` = '*****'
           1).  github.com/gogf/gf/v2/database/gdb.(*Core).DoCommit
                E:/gf-master/database/gdb/gdb_core_underlying.go:281
           2).  github.com/gogf/gf/contrib/drivers/clickhouse/v2.(*Driver).DoCommit
                C:/Users/wangshuai/go/pkg/mod/github.com/gogf/gf/contrib/drivers/clickhouse/v2@v2.2.5/clickhouse.go:276
           3).  github.com/gogf/gf/v2/database/gdb.(*Core).DoQuery
                E:/gf-master/database/gdb/gdb_core_underlying.go:74
           4).  github.com/gogf/gf/v2/database/gdb.(*Core).DoSelect
                E:/gf-master/database/gdb/gdb_core.go:144
           5).  github.com/gogf/gf/contrib/drivers/clickhouse/v2.(*Driver).TableFields
                C:/Users/wangshuai/go/pkg/mod/github.com/gogf/gf/contrib/drivers/clickhouse/v2@v2.2.5/clickhouse.go:160
           6).  github.com/gogf/gf/v2/database/gdb.(*DriverWrapperDB).TableFields.func1
                E:/gf-master/database/gdb/gdb_driver_wrapper_db.go:80
           7).  github.com/gogf/gf/v2/container/gmap.(*StrAnyMap).doSetWithLockCheck
                E:/gf-master/container/gmap/gmap_hash_str_any_map.go:217
           8).  github.com/gogf/gf/v2/container/gmap.(*StrAnyMap).GetOrSetFuncLock
                E:/gf-master/container/gmap/gmap_hash_str_any_map.go:254
           9).  github.com/gogf/gf/v2/database/gdb.(*DriverWrapperDB).TableFields
                E:/gf-master/database/gdb/gdb_driver_wrapper_db.go:78
           10). github.com/gogf/gf/cmd/gf/v2/internal/cmd/gendao.generateDaoSingle
                E:/gf-master/cmd/gf/internal/cmd/gendao/gendao_dao.go:51
           11). github.com/gogf/gf/cmd/gf/v2/internal/cmd/gendao.generateDao
                E:/gf-master/cmd/gf/internal/cmd/gendao/gendao_dao.go:30
           12). github.com/gogf/gf/cmd/gf/v2/internal/cmd/gendao.doGenDaoForArray
                E:/gf-master/cmd/gf/internal/cmd/gendao/gendao.go:278
           13). github.com/gogf/gf/cmd/gf/v2/internal/cmd/gendao.CGenDao.Dao
                E:/gf-master/cmd/gf/internal/cmd/gendao/gendao.go:186
           14). github.com/gogf/gf/v2/os/gcmd.newCommandFromMethod.func1
                E:/gf-master/os/gcmd/gcmd_command_object.go:317
           15). github.com/gogf/gf/v2/os/gcmd.(*Command).doRun
                E:/gf-master/os/gcmd/gcmd_command_run.go:152
           16). github.com/gogf/gf/v2/os/gcmd.(*Command).RunWithValueError
                E:/gf-master/os/gcmd/gcmd_command_run.go:91
           17). github.com/gogf/gf/v2/os/gcmd.(*Command).RunWithValue
                E:/gf-master/os/gcmd/gcmd_command_run.go:41
           18). github.com/gogf/gf/v2/os/gcmd.(*Command).Run
                E:/gf-master/os/gcmd/gcmd_command_run.go:35
           19). main.main
                E:/gf-master/cmd/gf/main.go:72

  48. 希望 tables 选项支持类似正则表达式的写法

  49. neo

    希望能生成从controller层到数据库的一套增删改查,那就方便很多了

  50. 针对postgresql的text[]数据类型,gf gen dao自动生成的格式为string格式,而非[]string格式

    postgresql版本采用最新的docker hub上的官方最新版本


  51. 有个疑问,使用gf gen dao 命令的时候,用参数指定数据库连接,居然不是最高优先级的。一直提示我数据库连接没有权限,然后才发现新克隆的代码库里面hack/下有个config.yaml文件,这个文件里的数据库配置,会覆盖命令行传参,这么设计有什么深意吗?

  52. 这个配置文件放在项目根目录才可以,是不是gf的默认路径没更新呀

    放不了图,我没有插入图片的权限。。。

    1. gf更新到2.3.3了就可以了

  53. 1.14 无法更新到2.3.3

  54. gen dao命令是否支持配置一个分组中的表,自动生成这些表的BaseEntity(这一组表结构含有一些相同字段,可以抽象为BaseEntity)?以便更好的使用内嵌结构的ORM支持?

  55. 为啥daoPath doPath entityPath 这几个参数没了啊 (| _ |)  调了好半天,最后发现是这几个参数不支持了,还有什么办法来指定一下dao do entity 的存放路径么?

    1. 在配置文件里指定:

      hack/config.yaml

      gfcli:
        gen:
          dao:
            - link:            "mysql:aaa:aaa@tcp(127.0.0.1:3306)/aaa"
              tables:          "aaa"
              removePrefix:    "gf_"
              descriptionTag:  true
              noModelComment:  true
              path: "./internal/app/aaa"

    2. 指定一个这几个目录的上级路径就可以

      1. 对 path的配置是没问题的,但是我项目中dao do entity都是在不同的目录中管理的。。 所以有没有什么办法可以分别指定这几个子目录啊

  56. 根据表生成的 model 里,支持去掉表里字段的前缀嘛?
    比如表里字段为 f_name,生成的 model 字段名称为 Name,而不是 FName

      1. removePrefix,针对的是表名称的前缀,不是表里字段的前缀

        1. 移除字段前缀? 好像没有这个配置

  57. 现在根据 sqlite 来生成 dao,当前版本还需要手动编译源码来生成 gf-cli 嘛?我看现在的源码并未被注释啊

  58. 大佬们,我执行gf gen dao后出现下面这个信息,它也不报错,但就是成功不了,dao的文件夹一直生成不了:

    2023-05-09 16:18:45.572 [DEBU] [  3 ms] [default] [rows:0  ] SHOW TABLES 
    done! 

    图片咋上传不了啊QAQ,反正出来的提示信息就是上面那些。是不是gf gen dao只针对Mac啊


    1. 我的goframe下载的应该是v2.4.1的,用的是windows系统

    2. 你数据库里面有没有数据表

  59. 执行migrate迁移数据库表的方法有吗?

    1. 你好,没有migrate功能哈。

  60. Hi,想请教在对接clickhouse时,表单数据类型是float32,gf gen dao生成的entity对于的类型却是float64,这是为什么?

    1. 可以检查源码实现,如果有需要可以提pr,也可以使用最新版本的TypeMapping特性自定义数据表字段类型转换的Golang类型。

  61. 生成的dao在goland中打开出错,代码也运行不起来

    // Transaction wraps the transaction logic using function f.
    // It rollbacks the transaction and returns the error from function f if it returns non-nil error.
    // It commits the transaction and returns nil if function f returns nil.
    //
    // Note that, you should not Commit or Rollback the transaction in function f
    // as it is automatically handled by this function.
    func (dao *BaseCommAdminDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
    return dao.Ctx(ctx).Transaction(ctx, f)
    }

    无法将 'f' (类型 func(ctx context.Context, tx *gdb.TX) error) 用作类型 func(ctx context.Context, tx TX) error


    service中的代码如下

    func (s *login) AdminStatus(ctx context.Context, req *st.LoginsmtReq) (res *st.LoginsmtRes, err error) {
    res = &st.LoginsmtRes{}

    adminInfo, _ := dao.BaseCommAdmin.Ctx(ctx).Where(dao.BaseCommAdmin.Columns().Username, req.Username).One()
    ...
    }
    命令行下报错:
    build error:
    # scibox_goframe/app/service/internal/dao/internal
    app\service\internal\dao\internal\base_comm_admin.go:103:39: cannot use f (variable of type func(ctx context.Context, tx *gdb.TX) error) as func(ctx context.Context, tx gdb.TX) error value in argument to dao.Ctx(ctx).Transaction

    1. 使用gf up -a命令升级最新CLI版本并自动修复不兼容变更。

      或者手动升级CLI版本,并使用gf fix命令。

  62. zhc

    dao生成的dao变量会去除“_” 变量变得特别那辨认

  63. gf gen dao --jsonCase Snake

    gf gen dao -j Snake

    没有生成上面文档中说的 aa_bb_cc这种格式 还是默认的 CamelLower,一定要配置hack/config.yaml 才能生效吗????但我又不想配置hack/config.yaml. 就直接用它,为什么不行呢!

    CLI Built Detail:
      Go Version:  go1.20.4
      GF Version:  v2.5.1
      Git Commit:  2023-07-26 21:27:58 e0e00434cc87d6edf64fc3df40ce7d3f40758794
      Build Time:  2023-07-26 21:32:56

  64. Jay

    CLI Built Detail:
      Go Version:  go1.20.4
      GF Version:  v2.5.1
      Git Commit:  2023-07-26 21:27:58 e0e00434cc87d6edf64fc3df40ce7d3f40758794
      Build Time:  2023-07-26 21:32:56

    hack/config.yaml

    gfcli:
    gen:
    dao:
    - link: "mysql:test:123456@tcp(127.0.0.1:3306)/wallet_evm"
    typeMapping:
    decimal:
    local: "decimal.Decimal"
    import: "github.com/shopspring/decimal"
    tables: ""
    daoPath: "app/server/wallet/dao/evm"
    doPath: "app/server/wallet/model/evm/do"
    entityPath: "app/server/wallet/model/evm/entity"
    descriptionTag: true

    表结构:

    CREATE TABLE `address_threshold` (
      `id` bigint unsigned NOT NULL AUTO_INCREMENT,
      `address_id` bigint unsigned NOT NULL COMMENT 'foreign key address id',
      `token_id` bigint unsigned NOT NULL COMMENT 'foreign key token id',
      `cold_threshold` decimal(64,18) NOT NULL COMMENT 'system amount greater than threshold will trigger hot to cold',
      `cold_reserve` decimal(64,18) NOT NULL COMMENT 'hot to cold reserve amount',
      `state` tinyint unsigned NOT NULL DEFAULT '1' COMMENT '0:disable, 1:enable',
      `created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
      `updated_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
      PRIMARY KEY (`id`) USING BTREE,
      UNIQUE KEY `uk_address` (`address_id`,`token_id`) USING BTREE
    ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;


    生成结果:

    type AddressThreshold struct {
    Id uint64 `json:"id" description:""` //
    AddressId uint64 `json:"addressId" description:"foreign key address id"` // foreign key address id
    TokenId uint64 `json:"tokenId" description:"foreign key token id"` // foreign key token id
    ColdThreshold string `json:"coldThreshold" description:"system amount greater than threshold will trigger hot to cold"` // system amount greater than threshold will trigger hot to cold
    ColdReserve string `json:"coldReserve" description:"hot to cold reserve amount"` // hot to cold reserve amount
    State uint `json:"state" description:"0:disable, 1:enable"` // 0:disable, 1:enable
    CreatedAt *gtime.Time `json:"createdAt" description:""` //
    UpdatedAt *gtime.Time `json:"updatedAt" description:""` //
    }

    没有像预期一样,生成decimal.Decimal
    1. `local: "decimal.Decimal"`应该修改为:`type: "decimal.Decimal"`

  65. gf gen dao,生成model的结构体没有数据类型是什么鬼?

    internal/model/entity:

    package entity
    
    import (
    	"github.com/gogf/gf/v2/os/gtime"
    )
    
    // TrainLoraTask is the golang structure for table train_lora_task.
    type TrainLoraTask struct {
    	Id          `json:"id"          ` //
    	Name        `json:"name"        ` //
    	Type        `json:"type"        ` //
    	CoverImgUrl `json:"coverImgUrl" ` // 封面图
    	CreatedAt   *gtime.Time           `json:"createdAt"   ` //
    	UpdatedAt   *gtime.Time           `json:"updatedAt"   ` //
    }

    internal/model/do:

    // =================================================================================
    // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
    // =================================================================================
    
    package do
    
    import (
    	"github.com/gogf/gf/v2/frame/g"
    	"github.com/gogf/gf/v2/os/gtime"
    )
    
    // TrainLoraTask is the golang structure of table train_lora_task for DAO operations like Where/Data.
    type TrainLoraTask struct {
    	g.Meta      `orm:"table:train_lora_task, do:true"`
    	Id                      //
    	Name                    //
    	Type                    //
    	CoverImgUrl             // 封面图
    	CreatedAt   *gtime.Time //
    	UpdatedAt   *gtime.Time //
    }


    gf -v:
    GoFrame CLI Tool v2.5.3, https://goframe.org
    GoFrame Version: v2.5.2 in current go.mod
    CLI Installed At: /usr/local/bin/gf
    CLI Built Detail:
      Go Version:  go1.20.6
      GF Version:  v2.5.3
      Git Commit:  2023-09-11 10:19:51 5bc9acdab3e2f5175a950de5b69e5cccaa5434eb
      Build Time:  2023-09-11 10:27:56

    1. 跟你一样你,你解决了吗?

      1. 没有,本人golang基础比较薄弱,没有仔细研究,需要作者帮忙看下

    2. 我也是,怎么解决啊

  66. GoFrame CLI Tool v2.5.4, https://goframe.org
    GoFrame Version: cannot find go.mod
    CLI Installed At: /usr/local/bin/gf
    CLI Built Detail:
      Go Version:  go1.20.8
      GF Version:  v2.5.4
      Git Commit:  2023-09-12 22:00:35 5219c5c37ed755ff5f717d6ec07c7a1951453991
      Build Time:  2023-09-12 22:17:31

    最新的生成dao 代码有问题

    func (dao *ResultDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
    return dao.Ctx(ctx).Transaction(ctx, f)
    }
    Cannot use 'f' (type func(ctx context.Context, tx gdb.TX) error) as the type func(ctx context.Context, tx *TX) error

    使用gf fix无法修复
  67. gf gen dao

    fetching tables fields failed for table "WF_PROCESS": dm.Open failed for driver "dm" without DB Name

    请教一下各位,有在gf里编译达梦的吗?我把dm的驱动开启后,重新编译了gf ,但是gf gen dao时,还是会出上面的提示

    在项目里dm的驱动是正常运行的,但是gf里就不行。

    我用的版本是 

    GoFrame CLI Tool v2.4.2, https://goframe.org
    GoFrame Version: v2.5.4 in current go.mod

    -----hack\config.yaml的内容 ----------

    gfcli:
      gen:
        dao:
          - link: "dm://AAAAAAAAA:AAAAAAAAA@127.0.0.1:5236/AAAAAAAAA?charset=utf8mb4&schema=AAAAAAAAA"
            user: "AAAAAAAAA"
            pass: "AAAAAAAAA"
            host: "127.0.0.1"
            port: "5236"
            name: "AAAAAAAAA"
            charset: "utf8mb4"
            schema: "AAAAAAAAA"
            debug: true
            tables:           "WF_PROCESS"
            removePrefix:    "gf_"
            descriptionTag:  true
            noModelComment:  true
            path:             "./internal/module/wf"

    1. 使用2.5.4版本试试,也可以自己拉代码编译哦

      1. 找到原因了,是配置的问题,驱动不支持link模式,但是又读不到配置数据引起的。

  68. 希望能生成从controller层到数据库的一套增删改查,那就方便很多了

  69. mysql数据库定义的字段是int 可为null类型, 使用gf gen dao 生成的entity实例确是 int类型, 如果生成的是指针 *int类型是不是更好?  
    因为数据库值是null时, 映射到int就变成了默认值0了, 这和预期的不符, 如果映射到*int后就可为null值了, 这是符合数据库设计的。
    请问有没有什么好的解决方案?

  70. gf gen dao生成snake json tag有问题:

    数据库字段:  script_md5


    internal/dao/internal/deploys.go json tag正常:
    {

        ScriptMd5: "script_md5",

    }

    model/entiry/deploys.go json tag错误:

    {

        ScriptMd5: "script_md_5",

    }


  71. 请问这两句貌似不生效怎么回事?

    没有改变,internal仍然没有dao 不是蛇形小写下划线命名

    daoPath:"dao"
    jsonCase: "Snake"
    1. 是cli版本的问题吗,我的goframe好像没有gf up命令 QAQ


  72. 多个数据库多个link命令行怎么写呢?

    1. gf2.6 gen dao -t big_data_saas_admin.adm_sys_role 用这种方式好像每个link都会生成一份文件

  73. mysql中是 bit(20) ,在gf gen dao生成代码的时候转化成了int,不影响吧?

    后续会做 位运算 查询

  74. 执行gf gen dao 后代码都被清空了.控制器,服务,逻辑,模型等文件夹代码都被清空了.这是啥问题呀?qq 2838386460,在线求助.执行命令无报错信息.

    gf version
    v2.6.3
    Welcome to GoFrame!
    Env Detail:
      Go Version: go1.22.0 windows/amd64
      GF Version(go.mod): cannot find go.mod
    CLI Detail:
      Installed At: C:\Users\Administrator\AppData\Local\Microsoft\WindowsApps\gf.exe
      Built Go Version: go1.20.8
      Built GF Version: v2.6.3
      Git Commit: 2024-02-07 17:11:36 d64a31fd1aa490ff9136c1776806f197d86c38a6
      Built Time: 2024-02-07 17:13:07
    Others Detail:
      Docs: https://goframe.org
      Now : 2024-03-03T08:46:14+08:00


  75. hack配置多个数据库时提示key错误,还有gf gen dao -l指定地址时仍然按照配置文件的link生成,这是咋回事

  76. 最新版本(v2.6.4),postgresql数据库,  bit(1) 转成了 int64, 而不是 bool,我记得之前版本是ok的啊!

  77. tables  这类定义,表多的时候只能逗号分开,又不支持前缀匹配,很不方便

    而一些配置文件本身是数据带类型的,比如  

     tables:
    	- users
    	- goods

    这样其实是可以直接解析为数组的 而且表多的时候一目了然

    但是因为gcfg为了兼容不带类型的配置文件,这里的定义目前只能写成逗号分开的,能不能考虑更新一下支持带数据类型的配置呢,这样  逗号分开或者多行数组都可以兼容解析为数组,因为配置文件本身就是文本,解析成 []string  应该够用了

  78. a

    希望增加一个选项,能在tag里自动加上omitempty

  79. 1、分表根据玩家uid%10获得表id,如 game_best_0,game_best_1,game_best_2,.......,game_best_9,共10张表,gf gen dao 生成四份go文件,只修改2份文件,这些表规律是从0到M,共M+1张表,逐步+1,所以将uid作为参数传入,现在可使用gf gen dao的数据库下创建同字段的game_best_,然后修改下列两个文件,删除game_best_表,防止重新生成覆盖

    以下为例子

    ./internal/dao/internal/game_best.go 

    package internal

    import (
        "context"
        "strconv"
        "github.com/gogf/gf/v2/database/gdb"
        "github.com/gogf/gf/v2/frame/g"
        "github.com/gogf/gf/v2/text/gstr"
    )

    // GameBestDao is the data access object for table game_best.
    type GameBestDao struct {
        table      string          // table is the underlying table name of the DAO.
        group      string          // group is the database configuration group name of current DAO.
        columns    GameBestColumns // columns contains all the column names of Table for convenient usage.
        tableCount int             //分表个数
    }

    // GameBestColumns defines and stores column names for table game_best.
    type GameBestColumns struct {
        Uid     string // 玩家id
        Money   string // 游戏币
        Diamond string // 钻石
        Score   string // 积分
        Exp     string // 经验
        Coin    string // 现金币
        Gcoin   string // 黄金币
    }

    // gameBestColumns holds the columns for table game_best.
    var gameBestColumns = GameBestColumns{
        Uid:     "uid",
        Money:   "money",
        Diamond: "diamond",
        Score:   "score",
        Exp:     "exp",
        Coin:    "coin",
        Gcoin:   "gcoin",
    }

    // NewGameBestDao creates and returns a new DAO object for table data access.
    func NewGameBestDao() *GameBestDao {
        return &GameBestDao{
            group:      "gamebest",
            table:      "game_best_",//除去末端数字余下部分
            columns:    gameBestColumns,
            tableCount: 10, //生成时候先算下分了多少表
        }
    }

    // DB retrieves and returns the underlying raw database management object of current DAO.
    func (dao *GameBestDao) DB() gdb.DB {
        return g.DB(dao.group)
    }

    // Table returns the table name of current dao.
    func (dao *GameBestDao) Table() string {
        return dao.table
    }

    // Columns returns all column names of current dao.
    func (dao *GameBestDao) Columns() GameBestColumns {
        return dao.columns
    }

    // Group returns the configuration group name of database of current dao.
    func (dao *GameBestDao) Group() string {
        return dao.group
    }

    // 获取分表个数
    func (dao *GameBestDao) TableCount() int {
        return dao.tableCount
    }

    // 处理分表,恢复实际表名
    func (dao *GameBestDao) setTable(uid int) string {
        var (
            remainder = uid % dao.tableCount
            str       = strconv.Itoa(remainder)
            array     = []string{dao.table, str}
            result    = gstr.Join(array, ``)
        )
        return result
    }

    // 改造后添加分表,按uid分表,作为传参
    // Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
    func (dao *GameBestDao) Ctx(ctx context.Context, uid int) *gdb.Model {
        return dao.DB().Model(dao.setTable(uid)).Safe().Ctx(ctx)
    }

    // 改造后添加分表,按uid分表,作为传参
    // Transaction wraps the transaction logic using function f.
    // It rollbacks the transaction and returns the error from function f if it returns non-nil error.
    // It commits the transaction and returns nil if function f returns nil.
    //
    // Note that, you should not Commit or Rollback the transaction in function f
    // as it is automatically handled by this function.
    func (dao *GameBestDao) Transaction(ctx context.Context, uid int, f func(ctx context.Context, tx gdb.TX) error) (err error) {
        return dao.Ctx(ctx, uid).Transaction(ctx, f)
    }

    ---------------------------------------------------------------我是分隔符------------------------------------------------------------------------------

    ----------------------------------------------------------------我是分隔符-----------------------------------------------------------------------------

    ./internal/model/do/game_best.go

    package do

    import (
        "fmt"
        "reflect"

        "github.com/gogf/gf/v2/frame/g"
    )

    // GameBest is the golang structure of table game_best for DAO operations like Where/Data.
    type GameBestBase struct {
        Uid     interface{} // 玩家id
        Money   interface{} // 游戏币
        Diamond interface{} // 钻石
        Score   interface{} // 积分
        Exp     interface{} // 经验
        Coin    interface{} // 现金币
        Gcoin   interface{} // 黄金币
    }
    type GameBest0 struct {
        g.Meta `orm:"table:game_best_0, do:true"`
        GameBestBase
    }
    type GameBest1 struct {
        g.Meta `orm:"table:game_best_1, do:true"`
        GameBestBase
    }
    type GameBest2 struct {
        g.Meta `orm:"table:game_best_2, do:true"`
        GameBestBase
    }
    type GameBest3 struct {
        g.Meta `orm:"table:game_best_3, do:true"`
        GameBestBase
    }
    type GameBest4 struct {
        g.Meta `orm:"table:game_best_4, do:true"`
        GameBestBase
    }
    type GameBest5 struct {
        g.Meta `orm:"table:game_best_5, do:true"`
        GameBestBase
    }
    type GameBest6 struct {
        g.Meta `orm:"table:game_best_6, do:true"`
        GameBestBase
    }
    type GameBest7 struct {
        g.Meta `orm:"table:game_best_7, do:true"`
        GameBestBase
    }
    type GameBest8 struct {
        g.Meta `orm:"table:game_best_8, do:true"`
        GameBestBase
    }
    type GameBest9 struct {
        g.Meta `orm:"table:game_best_9, do:true"`
        GameBestBase
    }

    // 创建一个map来存储不同类型的GameBestX结构体实例
    var GameBestMap = map[string]interface{}{
        "GameBest0": &GameBest0{},
        "GameBest1": &GameBest1{},
        "GameBest2": &GameBest2{},
        "GameBest3": &GameBest3{},
        "GameBest4": &GameBest4{},
        "GameBest5": &GameBest5{},
        "GameBest6": &GameBest6{},
        "GameBest7": &GameBest7{},
        "GameBest8": &GameBest8{},
        "GameBest9": &GameBest9{},
    }

    // 创建和设置用户信息的函数
    func CreateAndSetGameBest(uid int, in GameBestBase) (any, error) {
        // 根据uid的值计算对应的结构体类型
        GameBestType := fmt.Sprintf("GameBest%d", uid%10)
        // 从map中获取对应的结构体实例
        if GameBest, ok := GameBestMap[GameBestType]; ok {
            // 使用反射设置结构体字段的值
            val := reflect.ValueOf(GameBest).Elem()
            SetGameBestField(val, "Uid", in.Uid)
            SetGameBestField(val, "Money", in.Money)
            SetGameBestField(val, "Diamond", in.Diamond)
            SetGameBestField(val, "Score", in.Score)
            SetGameBestField(val, "Exp", in.Exp)
            SetGameBestField(val, "Coin", in.Coin)
            SetGameBestField(val, "Gcoin", in.Gcoin)
            return GameBest, nil
        }
        return nil, fmt.Errorf("unsupported user info type: %s", GameBestType)
    }

    // 使用反射设置结构体字段的值的辅助函数
    func SetGameBestField(val reflect.Value, fieldName string, value interface{}) error {
        field := val.FieldByName(fieldName)
        if field.IsValid() && field.CanSet() {
            field.Set(reflect.ValueOf(value))
        }
        return nil
    }

    ------------------------------------我是分隔符-------------------------------------------------

    ------------------------------------我是分隔符-------------------------------------------------

    使用dao对分表操作

    // 生成玩家信息表
    func CreateGameUserInfo(ctx context.Context, in model.GameLoginInput, uid int) (err error) {
        var userinfo any
        if userinfo, err = do.CreateAndSetUserInfo(uid, do.UserInfoBase{
            Uid:        uid,
            Cid:        in.Cid,
            Lid:        in.Lid,
            Status:     1,
            Nick:       "Guest",
            Sex:        0,
            Icon:       "",
            UpdateTime: gtime.Timestamp(),
            CreateTime: gtime.Timestamp(),
        }); err != nil {
            return err
        }

        dao.UserInfo.Transaction(ctx, uid, func(ctx context.Context, tx gdb.TX) (err error) {
            _, err = dao.UserInfo.Ctx(ctx, uid).Data(userinfo).Insert()
            return err
        })
        return err
    }


    2、根据年月周日规则生成表,比如 年表 order_sum_2024,月表order_202404,周表order_202434,日表order_20240425,这些表的规则就是数字部分固定长度,无法确定规则(周与月有相同数字),所以将这些数字作为参数传入,并且需要定时生成新表及修改文件,如果能加入gf gen dao 参数生成规则最好了,可以定时刷新

    余数的也可以改成这个规则,传入的参数在login判断可能更简单,其他非数字的有规律的分表,同理可操作

    以下为例子

    ./internal/dao/internal/game_best.go 

    package internal

    import (
        "context"
        "strconv"
        "github.com/gogf/gf/v2/database/gdb"
        "github.com/gogf/gf/v2/frame/g"
        "github.com/gogf/gf/v2/text/gstr"
    )

    。。。。

    // NewGameBestDao creates and returns a new DAO object for table data access.
    func NewGameBestDao() *GameBestDao {
        return &GameBestDao{
            group:      "gamebest",
            table:      "order_",//除去末端数字余下部分
            columns:    gameBestColumns,
        }
    }

    。。。。。。

    // 处理分表,恢复实际表名
    func (dao *GameBestDao) setTable(uid int) string {
        var (
            str       = strconv.Itoa(uid)
            array     = []string{dao.table, str}
            result    = gstr.Join(array, ``)
        )
        return result
    }

    // 改造后添加分表,按uid分表,作为传参
    // Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
    func (dao *GameBestDao) Ctx(ctx context.Context, uid int) *gdb.Model {
        return dao.DB().Model(dao.setTable(uid)).Safe().Ctx(ctx)
    }

    // 改造后添加分表,按uid分表,作为传参
    // Transaction wraps the transaction logic using function f.
    // It rollbacks the transaction and returns the error from function f if it returns non-nil error.
    // It commits the transaction and returns nil if function f returns nil.
    //
    // Note that, you should not Commit or Rollback the transaction in function f
    // as it is automatically handled by this function.
    func (dao *GameBestDao) Transaction(ctx context.Context, uid int, f func(ctx context.Context, tx gdb.TX) error) (err error) {
        return dao.Ctx(ctx, uid).Transaction(ctx, f)
    }

    ./internal/model/do/game_best.go

    与上面文件类似即可

    1. 分表操作表名用hook就可以了

  80. 请问typeMapping中如何将tinyint unsigned设置为uint8呢?

  81. 郭强 目前计划将已有gin项目迁移到goframe中,遇到一个问题是原来代码中结构体名为User,表名为users。在goframe2.7.2中用gf gen dao 时会提示user表不存在。在加了字段g.Meta `orm:"table:users"`也不生效,请问如何解决。

    因为是已有项目迁移,不能动数据库

  82. 郭强 现在执行`gf gen dao`会将do,entity下的整个文件内容替换成新的,这样就没法在文件内定义对do, entity的模型操作方法(这就默认生成的数据模型是失血模型?)。但是我们通常习惯将一些对模型的简单操作,比如字段值的处理,状态的变更放在这边,复用的同时可以减少logic的代码量(这应该算是贫血模型?)。示例如下:

    示例
    type User struct {
    	Status int
    }
    
    func (u *User) changeStatus(status int) {
    	u.Status = status
    }
    
    


    这种情况我觉得可以提供仅替换数据模型的选项参数,通过对文件内容的匹配进行替换,而不是整个文件内容根据模版生成的内容替换写入