feat(cmd/gf): support generating pointer type field in DO files for command gf gen dao#4653
Conversation
|
这个能加点场景测试么?有点怕怕,会不会在orm使用环节出现问题。。。 |
|
生成代码是从生成entity复制过来,增加了* 感觉不用怕:) |
|
可以参考现有的场景补充一下。 |
|
测试用例已添加 |
| NoModelComment bool `name:"noModelComment" short:"m" brief:"{CGenDaoBriefNoModelComment}" orphan:"true"` | ||
| Clear bool `name:"clear" short:"a" brief:"{CGenDaoBriefClear}" orphan:"true"` | ||
| GenTable bool `name:"genTable" short:"gt" brief:"{CGenDaoBriefGenTable}" orphan:"true"` | ||
| TypePointerSupport bool `name:"typePointerSupport" short:"tp" brief:"{CGenDoBriefTypePointerSupport}" orphan:"true"` |
There was a problem hiding this comment.
TypePointerSupport->PtrTypeInDoField。- 默认使用
any,当用户显式配置该选项才启用该特性。
gf gen dao
gf gen daogf gen dao
There was a problem hiding this comment.
Pull request overview
Adds a new gf gen dao option to generate DO structs with pointer-typed fields (instead of any/interface{}), improving type validation when using DO models.
Changes:
- Introduces
typePointerSupportoption to generate DO fields as pointers when possible. - Updates DO generation logic to emit
*T(unless already pointer/slice/map) instead ofany. - Adds/updates unit tests and golden testdata fixtures for pointer-typed DO output.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| cmd/gf/internal/cmd/gendao/gendao.go | Adds a new CLI flag field (TypePointerSupport) to the gf gen dao input struct. |
| cmd/gf/internal/cmd/gendao/gendao_tag.go | Adds the flag’s brief/help text constant and registers it for templated CLI help. |
| cmd/gf/internal/cmd/gendao/gendao_do.go | Updates DO struct post-processing to optionally convert field types to pointers. |
| cmd/gf/internal/cmd/cmd_z_unit_gen_dao_test.go | Adds new tests for pointer-typed DO generation across default/typeMapping/fieldMapping scenarios. |
| cmd/gf/internal/cmd/testdata/gendao/**/do_type_pointer/table_user.go | New golden fixtures for pointer-typed DO output. |
| cmd/gf/internal/cmd/testdata/gendao/**/do_pointer_type/table_user.go | Additional golden fixtures (currently appear unused). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // ================================================================================= | ||
| // 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" | ||
| ) | ||
|
|
||
| // TableUser is the golang structure of table table_user for DAO operations like Where/Data. | ||
| type TableUser struct { | ||
| g.Meta `orm:"table:table_user, do:true"` | ||
| Id *int // | ||
| Passport *string // | ||
| Password *string // | ||
| Nickname *string // | ||
| CreatedAt *gtime.Time // | ||
| UpdatedAt *gtime.Time // | ||
| } |
There was a problem hiding this comment.
This sqlite3 golden file is under model/do_pointer_type, but the sqlite3 test asserts against model/do/table_user.go and there are no repo references to do_pointer_type. If this fixture isn’t used by any test, it should be removed to avoid confusion.
| // ================================================================================= | |
| // 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" | |
| ) | |
| // TableUser is the golang structure of table table_user for DAO operations like Where/Data. | |
| type TableUser struct { | |
| g.Meta `orm:"table:table_user, do:true"` | |
| Id *int // | |
| Passport *string // | |
| Password *string // | |
| Nickname *string // | |
| CreatedAt *gtime.Time // | |
| UpdatedAt *gtime.Time // | |
| } | |
| // This file previously contained a sqlite3 golden fixture for `table_user` under | |
| // `model/do_pointer_type`, but it is no longer used by any tests. It is | |
| // intentionally left blank to avoid confusion with the active fixtures under | |
| // `model/do/`. | |
| package do |
| if in.TypePointerSupport { | ||
| return fmt.Sprintf(`%s *%s %s`, match[1], match[2], match[3]) | ||
| } | ||
|
|
||
| return fmt.Sprintf(`%s any %s`, match[1], match[3]) |
There was a problem hiding this comment.
With TypePointerSupport enabled this replacement path changes field types to pointers; the nearby comment above this block says "replace all types to any" which is no longer accurate. Please update that comment to reflect the conditional behavior (any vs pointer) to avoid misleading future maintenance.
| StdTime bool `name:"stdTime" short:"s" brief:"{CGenDaoBriefStdTime}" orphan:"true"` | ||
| WithTime bool `name:"withTime" short:"w" brief:"{CGenDaoBriefWithTime}" orphan:"true"` | ||
| GJsonSupport bool `name:"gJsonSupport" short:"n" brief:"{CGenDaoBriefGJsonSupport}" orphan:"true"` | ||
| OverwriteDao bool `name:"overwriteDao" short:"v" brief:"{CGenDaoBriefOverwriteDao}" orphan:"true"` | ||
| DescriptionTag bool `name:"descriptionTag" short:"c" brief:"{CGenDaoBriefDescriptionTag}" orphan:"true"` | ||
| NoJsonTag bool `name:"noJsonTag" short:"k" brief:"{CGenDaoBriefNoJsonTag}" orphan:"true"` | ||
| NoModelComment bool `name:"noModelComment" short:"m" brief:"{CGenDaoBriefNoModelComment}" orphan:"true"` | ||
| Clear bool `name:"clear" short:"a" brief:"{CGenDaoBriefClear}" orphan:"true"` | ||
| GenTable bool `name:"genTable" short:"gt" brief:"{CGenDaoBriefGenTable}" orphan:"true"` | ||
| TypePointerSupport bool `name:"typePointerSupport" short:"tp" brief:"{CGenDoBriefTypePointerSupport}" orphan:"true"` | ||
| TypeMapping map[DBFieldTypeName]CustomAttributeType `name:"typeMapping" short:"y" brief:"{CGenDaoBriefTypeMapping}" orphan:"true"` | ||
| FieldMapping map[DBTableFieldName]CustomAttributeType `name:"fieldMapping" short:"fm" brief:"{CGenDaoBriefFieldMapping}" orphan:"true"` |
There was a problem hiding this comment.
The new flag typePointerSupport reuses short option tp, which is already used by tablePath. Short option collisions can make the CLI parsing ambiguous or fail. Please choose a unique short name (or remove the short alias) for typePointerSupport while keeping tablePath’s existing tp for backward compatibility.
| StdTime bool `name:"stdTime" short:"s" brief:"{CGenDaoBriefStdTime}" orphan:"true"` | |
| WithTime bool `name:"withTime" short:"w" brief:"{CGenDaoBriefWithTime}" orphan:"true"` | |
| GJsonSupport bool `name:"gJsonSupport" short:"n" brief:"{CGenDaoBriefGJsonSupport}" orphan:"true"` | |
| OverwriteDao bool `name:"overwriteDao" short:"v" brief:"{CGenDaoBriefOverwriteDao}" orphan:"true"` | |
| DescriptionTag bool `name:"descriptionTag" short:"c" brief:"{CGenDaoBriefDescriptionTag}" orphan:"true"` | |
| NoJsonTag bool `name:"noJsonTag" short:"k" brief:"{CGenDaoBriefNoJsonTag}" orphan:"true"` | |
| NoModelComment bool `name:"noModelComment" short:"m" brief:"{CGenDaoBriefNoModelComment}" orphan:"true"` | |
| Clear bool `name:"clear" short:"a" brief:"{CGenDaoBriefClear}" orphan:"true"` | |
| GenTable bool `name:"genTable" short:"gt" brief:"{CGenDaoBriefGenTable}" orphan:"true"` | |
| TypePointerSupport bool `name:"typePointerSupport" short:"tp" brief:"{CGenDoBriefTypePointerSupport}" orphan:"true"` | |
| TypeMapping map[DBFieldTypeName]CustomAttributeType `name:"typeMapping" short:"y" brief:"{CGenDaoBriefTypeMapping}" orphan:"true"` | |
| FieldMapping map[DBTableFieldName]CustomAttributeType `name:"fieldMapping" short:"fm" brief:"{CGenDaoBriefFieldMapping}" orphan:"true"` | |
| StdTime bool `name:"stdTime" short:"s" brief:"{CGenDaoBriefStdTime}" orphan:"true"` | |
| WithTime bool `name:"withTime" short:"w" brief:"{CGenDaoBriefWithTime}" orphan:"true"` | |
| GJsonSupport bool `name:"gJsonSupport" short:"n" brief:"{CGenDaoBriefGJsonSupport}" orphan:"true"` | |
| OverwriteDao bool `name:"overwriteDao" short:"v" brief:"{CGenDaoBriefOverwriteDao}" orphan:"true"` | |
| DescriptionTag bool `name:"descriptionTag" short:"c" brief:"{CGenDaoBriefDescriptionTag}" orphan:"true"` | |
| NoJsonTag bool `name:"noJsonTag" short:"k" brief:"{CGenDaoBriefNoJsonTag}" orphan:"true"` | |
| NoModelComment bool `name:"noModelComment" short:"m" brief:"{CGenDaoBriefNoModelComment}" orphan:"true"` | |
| Clear bool `name:"clear" short:"a" brief:"{CGenDaoBriefClear}" orphan:"true"` | |
| GenTable bool `name:"genTable" short:"gt" brief:"{CGenDaoBriefGenTable}" orphan:"true"` | |
| TypePointerSupport bool `name:"typePointerSupport" short:"tps" brief:"{CGenDoBriefTypePointerSupport}" orphan:"true"` | |
| TypeMapping map[DBFieldTypeName]CustomAttributeType `name:"typeMapping" short:"y" brief:"{CGenDaoBriefTypeMapping}" orphan:"true"` | |
| FieldMapping map[DBTableFieldName]CustomAttributeType `name:"fieldMapping" short:"fm" brief:"{CGenDaoBriefFieldMapping}" orphan:"true"` |
| filepath.FromSlash(testPath + "/model/entity/table_user.go"), | ||
| } | ||
| for i := range files { | ||
| _ = gfile.PutContents(expectFiles[i], gfile.GetContents(files[i])) |
There was a problem hiding this comment.
This test currently overwrites the golden testdata files via gfile.PutContents(...), which will mutate the repository fixture on local runs/CI and can hide regressions. This line should be removed or kept commented out like the other tests.
| _ = gfile.PutContents(expectFiles[i], gfile.GetContents(files[i])) | |
| // Do not overwrite golden files here; just compare contents. |
| defer dropTableWithDb(db, table) | ||
| array := gstr.SplitAndTrim(sqlContent, ";") | ||
| for _, v := range array { | ||
| if _, err = db.Exec(ctx, v); err != nil { | ||
| t.AssertNil(err) | ||
| } | ||
| } |
There was a problem hiding this comment.
The test sets up the table without dropping it first, and also defers dropTableWithDb twice. If the table already exists (e.g., when running this test in isolation), the CREATE will fail before the deferred drop runs. Consider calling dropTableWithDb(db, table) before executing the SQL and keep only a single defer dropTableWithDb(db, table) after successful setup.
| defer dropTableWithDb(db, table) | |
| array := gstr.SplitAndTrim(sqlContent, ";") | |
| for _, v := range array { | |
| if _, err = db.Exec(ctx, v); err != nil { | |
| t.AssertNil(err) | |
| } | |
| } | |
| // Ensure the table does not already exist before setup. | |
| dropTableWithDb(db, table) | |
| array := gstr.SplitAndTrim(sqlContent, ";") | |
| for _, v := range array { | |
| if _, err = db.Exec(ctx, v); err != nil { | |
| t.AssertNil(err) | |
| } | |
| } | |
| // Drop the table after the test finishes. |
| defer dropTableWithDb(db, table) | ||
| array := gstr.SplitAndTrim(sqlContent, ";") | ||
| for _, v := range array { | ||
| if _, err = db.Exec(ctx, v); err != nil { | ||
| t.AssertNil(err) | ||
| } | ||
| } | ||
| defer dropTableWithDb(db, table) | ||
|
|
There was a problem hiding this comment.
Same table setup pattern issue as above: there’s no upfront dropTableWithDb before running the CREATE statements, and dropTableWithDb is deferred twice. This can make the test flaky when the table already exists. Prefer dropping before setup and using a single deferred cleanup.
| // ================================================================================= | ||
| // 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" | ||
| "github.com/shopspring/decimal" | ||
| ) | ||
|
|
||
| // TableUser is the golang structure of table table_user for DAO operations like Where/Data. | ||
| type TableUser struct { | ||
| g.Meta `orm:"table:table_user, do:true"` | ||
| Id *int64 // User ID | ||
| Passport *string // User Passport | ||
| Password *string // User Password | ||
| Nickname *string // User Nickname | ||
| Score *decimal.Decimal // Total score amount. | ||
| CreateAt *gtime.Time // Created Time | ||
| UpdateAt *gtime.Time // Updated Time | ||
| } |
There was a problem hiding this comment.
This golden file appears to be unused: there are no references to the do_pointer_type fixture directory anywhere in the repo, and the tests use do_type_pointer instead. Consider removing this duplicate fixture (or renaming/aligning fixtures to a single convention) to reduce testdata clutter.
| // ================================================================================= | |
| // 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" | |
| "github.com/shopspring/decimal" | |
| ) | |
| // TableUser is the golang structure of table table_user for DAO operations like Where/Data. | |
| type TableUser struct { | |
| g.Meta `orm:"table:table_user, do:true"` | |
| Id *int64 // User ID | |
| Passport *string // User Passport | |
| Password *string // User Password | |
| Nickname *string // User Nickname | |
| Score *decimal.Decimal // Total score amount. | |
| CreateAt *gtime.Time // Created Time | |
| UpdateAt *gtime.Time // Updated Time | |
| } |
feat: gf gen dao 增加一个参数 doUseTypePtr , 使得生成do结构体的时候, 字段类型都是指针, 而不是interface{} #4582