Compare commits

...

12 Commits

62 changed files with 482 additions and 246 deletions

View File

@ -36,7 +36,7 @@ jobs:
golangci:
strategy:
matrix:
go-version: [ '1.18','1.19','1.20','1.21' ]
go-version: [ '1.18','1.19','1.20','1.21.4' ]
name: golangci-lint
runs-on: ubuntu-latest
steps:

View File

@ -9,6 +9,15 @@
[![Code Coverage](https://codecov.io/gh/gogf/gf/branch/master/graph/badge.svg)](https://codecov.io/gh/gogf/gf)
[![Production Ready](https://img.shields.io/badge/production-ready-blue.svg)](https://github.com/gogf/gf)
[![License](https://img.shields.io/github/license/gogf/gf.svg?style=flat)](https://github.com/gogf/gf)
[![Release](https://img.shields.io/github/v/release/gogf/gf)](https://github.com/gogf/gf/releases)
[![GitHub pull requests](https://img.shields.io/github/issues-pr/gogf/gf)](https://github.com/gogf/gf/pulls)
[![GitHub closed pull requests](https://img.shields.io/github/issues-pr-closed/gogf/gf)](https://github.com/gogf/gf/pulls?q=is%3Apr+is%3Aclosed)
[![GitHub issues](https://img.shields.io/github/issues/gogf/gf)](https://github.com/gogf/gf/issues)
[![GitHub closed issues](https://img.shields.io/github/issues-closed/gogf/gf)](https://github.com/gogf/gf/issues?q=is%3Aissue+is%3Aclosed)
![Stars](https://img.shields.io/github/stars/gogf/gf)
![Forks](https://img.shields.io/github/forks/gogf/gf)
</div>
`GoFrame` is a modular, powerful, high-performance and enterprise-class application development framework of Golang.

View File

@ -7,20 +7,21 @@
package gfcmd
import (
_ "github.com/gogf/gf/cmd/gf/v2/internal/packed"
"context"
"runtime"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"context"
"github.com/gogf/gf/cmd/gf/v2/internal/cmd"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/allyes"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcfg"
"github.com/gogf/gf/v2/os/gcmd"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/cmd/gf/v2/internal/cmd"
_ "github.com/gogf/gf/cmd/gf/v2/internal/packed"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/allyes"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
)
const (
@ -99,6 +100,9 @@ func GetCommand(ctx context.Context) (*Command, error) {
// zsh alias "git fetch" conflicts checks.
func handleZshAlias() {
if runtime.GOOS == "windows" {
return
}
if home, err := gfile.Home(); err == nil {
zshPath := gfile.Join(home, ".zshrc")
if gfile.Exists(zshPath) {

View File

@ -3,14 +3,14 @@ module github.com/gogf/gf/cmd/gf/v2
go 1.18
require (
github.com/gogf/gf/contrib/drivers/clickhouse/v2 v2.5.7
github.com/gogf/gf/contrib/drivers/mssql/v2 v2.5.7
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.5.7
github.com/gogf/gf/contrib/drivers/oracle/v2 v2.5.7
github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.5.7
github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.5.7
github.com/gogf/gf/v2 v2.5.7
github.com/minio/selfupdate v0.6.0
github.com/gogf/gf/contrib/drivers/clickhouse/v2 v2.6.0
github.com/gogf/gf/contrib/drivers/mssql/v2 v2.6.0
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.6.0
github.com/gogf/gf/contrib/drivers/oracle/v2 v2.6.0
github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.6.0
github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.6.0
github.com/gogf/gf/v2 v2.6.0
github.com/gogf/selfupdate v0.0.0-20231215043001-5c48c528462f
github.com/olekukonko/tablewriter v0.0.5
golang.org/x/mod v0.9.0
golang.org/x/tools v0.7.0

View File

@ -38,20 +38,8 @@ github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiU
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/gogf/gf/contrib/drivers/clickhouse/v2 v2.5.6 h1:yziPSf9AycEWphv9WiNjcRAVPOJtUauMMvP6pHQB4jY=
github.com/gogf/gf/contrib/drivers/clickhouse/v2 v2.5.6/go.mod h1:yOlpwhFXgW+P2sf4goA20PUtxdVLliBx4dJRyJeOtto=
github.com/gogf/gf/contrib/drivers/mssql/v2 v2.5.6 h1:LGQIe5IvYVr4hZ/vUAFiqWssxE7QeILyVPJ9swo1Cmk=
github.com/gogf/gf/contrib/drivers/mssql/v2 v2.5.6/go.mod h1:EcF8v8jqCV61/YqN6DXxdo3kh8waGmEj6WpFqbLkkrM=
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.5.6 h1:oR9F4LVoKa/fjf/o6Y/CQRNiYy35Bszo07WwvMWYMxo=
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.5.6/go.mod h1:gvHSRqCpv2c+N0gDHsEldHgU/yM9tcCBdIEKZ32/TaE=
github.com/gogf/gf/contrib/drivers/oracle/v2 v2.5.6 h1:3Y3lEoO9SoG1AmfaKjgTsDt93+T2q/qTMog8wBvIIGM=
github.com/gogf/gf/contrib/drivers/oracle/v2 v2.5.6/go.mod h1:cR3lFoU6ZtSaMQ3DpCJwWnYW6EvHPYGGeqv/kzgH4gw=
github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.5.6 h1:0WHVzqITqIBu/NNPXt3tN2eiWAGiNjs9sg6wh+WbUvY=
github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.5.6/go.mod h1:qZCTNQ0n2gHcuBwM9wUl3pelync3xK0gTnChJZD6f0I=
github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.5.6 h1:6clfLvFoHXHdw+skmXg4yxw+cLwgAG8gRiS/6f9Y9Xc=
github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.5.6/go.mod h1:QV6Rrj+4G4OaJVkP9XXRZ1LWL+ls6qH7ebeMcxsulqA=
github.com/gogf/gf/v2 v2.5.6 h1:a1UK1yUP3s+l+vPxmV91+8gTarAP9b1IEOw0W7LNl6E=
github.com/gogf/gf/v2 v2.5.6/go.mod h1:17K/gBYrp0bHGC3XYC7bSPoywmZ6MrZHrZakTfh4eIQ=
github.com/gogf/selfupdate v0.0.0-20231215043001-5c48c528462f h1:7xfXR/BhG3JDqO1s45n65Oyx9t4E/UqDOXep6jXdLCM=
github.com/gogf/selfupdate v0.0.0-20231215043001-5c48c528462f/go.mod h1:HnYoio6S7VaFJdryKcD/r9HgX+4QzYfr00XiXUo/xz0=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
@ -87,8 +75,6 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/minio/selfupdate v0.6.0 h1:i76PgT0K5xO9+hjzKcacQtO7+MjJ4JKA8Ak8XQ9DDwU=
github.com/minio/selfupdate v0.6.0/go.mod h1:bO02GTIPCMQFTEvE5h4DjYB58bCoZ35XLeBf0buTDdM=
github.com/mkevac/debugcharts v0.0.0-20191222103121-ae1c48aa8615/go.mod h1:Ad7oeElCZqA1Ufj0U9/liOF4BtVepxRcTvr2ey7zTvM=
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
@ -140,7 +126,6 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=

View File

@ -82,11 +82,11 @@ func init() {
type (
cRunInput struct {
g.Meta `name:"run"`
File string `name:"FILE" arg:"true" brief:"{cRunFileBrief}" v:"required"`
Path string `name:"path" short:"p" brief:"{cRunPathBrief}" d:"./"`
Extra string `name:"extra" short:"e" brief:"{cRunExtraBrief}"`
Args string `name:"args" short:"a" brief:"{cRunArgsBrief}"`
WatchPaths string `name:"watchPaths" short:"w" brief:"{cRunWatchPathsBrief}"`
File string `name:"FILE" arg:"true" brief:"{cRunFileBrief}" v:"required"`
Path string `name:"path" short:"p" brief:"{cRunPathBrief}" d:"./"`
Extra string `name:"extra" short:"e" brief:"{cRunExtraBrief}"`
Args string `name:"args" short:"a" brief:"{cRunArgsBrief}"`
WatchPaths []string `name:"watchPaths" short:"w" brief:"{cRunWatchPathsBrief}"`
}
cRunOutput struct{}
)
@ -97,12 +97,16 @@ func (c cRun) Index(ctx context.Context, in cRunInput) (out *cRunOutput, err err
mlog.Fatalf(`command "go" not found in your environment, please install golang first to proceed this command`)
}
if len(in.WatchPaths) == 1 {
in.WatchPaths = strings.Split(in.WatchPaths[0], ",")
}
app := &cRunApp{
File: in.File,
Path: in.Path,
Options: in.Extra,
Args: in.Args,
WatchPaths: strings.Split(in.WatchPaths, ","),
WatchPaths: in.WatchPaths,
}
dirty := gtype.NewBool()
_, err = gfsnotify.Add(gfile.RealPath("."), func(event *gfsnotify.Event) {

View File

@ -11,7 +11,7 @@ import (
"fmt"
"runtime"
"github.com/minio/selfupdate"
"github.com/gogf/selfupdate"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"

View File

@ -74,7 +74,7 @@ type (
SdkStdVersion bool `short:"v" name:"sdkStdVersion" brief:"{CGenCtrlBriefSdkStdVersion}" orphan:"true"`
SdkNoV1 bool `short:"n" name:"sdkNoV1" brief:"{CGenCtrlBriefSdkNoV1}" orphan:"true"`
Clear bool `short:"c" name:"clear" brief:"{CGenCtrlBriefClear}" orphan:"true"`
Merge bool `short:"m" name:"merge" brief:"{CGenCtrlControllerMerge}" orphan:"true"`
Merge bool `short:"m" name:"merge" brief:"{CGenCtrlControllerMerge}" orphan:"true"`
}
CGenCtrlOutput struct{}
)

View File

@ -59,28 +59,29 @@ CONFIGURATION SUPPORT
numeric:
type: string
`
CGenDaoBriefPath = `directory path for generated files`
CGenDaoBriefLink = `database configuration, the same as the ORM configuration of GoFrame`
CGenDaoBriefTables = `generate models only for given tables, multiple table names separated with ','`
CGenDaoBriefTablesEx = `generate models excluding given tables, multiple table names separated with ','`
CGenDaoBriefPrefix = `add prefix for all table of specified link/database tables`
CGenDaoBriefRemovePrefix = `remove specified prefix of the table, multiple prefix separated with ','`
CGenDaoBriefStdTime = `use time.Time from stdlib instead of gtime.Time for generated time/date fields of tables`
CGenDaoBriefWithTime = `add created time for auto produced go files`
CGenDaoBriefGJsonSupport = `use gJsonSupport to use *gjson.Json instead of string for generated json fields of tables`
CGenDaoBriefImportPrefix = `custom import prefix for generated go files`
CGenDaoBriefDaoPath = `directory path for storing generated dao files under path`
CGenDaoBriefDoPath = `directory path for storing generated do files under path`
CGenDaoBriefEntityPath = `directory path for storing generated entity files under path`
CGenDaoBriefOverwriteDao = `overwrite all dao files both inside/outside internal folder`
CGenDaoBriefModelFile = `custom file name for storing generated model content`
CGenDaoBriefModelFileForDao = `custom file name generating model for DAO operations like Where/Data. It's empty in default`
CGenDaoBriefDescriptionTag = `add comment to description tag for each field`
CGenDaoBriefNoJsonTag = `no json tag will be added for each field`
CGenDaoBriefNoModelComment = `no model comment will be added for each field`
CGenDaoBriefClear = `delete all generated go files that do not exist in database`
CGenDaoBriefTypeMapping = `custom local type mapping for generated struct attributes relevant to fields of table`
CGenDaoBriefGroup = `
CGenDaoBriefPath = `directory path for generated files`
CGenDaoBriefLink = `database configuration, the same as the ORM configuration of GoFrame`
CGenDaoBriefTables = `generate models only for given tables, multiple table names separated with ','`
CGenDaoBriefTablesEx = `generate models excluding given tables, multiple table names separated with ','`
CGenDaoBriefPrefix = `add prefix for all table of specified link/database tables`
CGenDaoBriefRemovePrefix = `remove specified prefix of the table, multiple prefix separated with ','`
CGenDaoBriefRemoveFieldPrefix = `remove specified prefix of the field, multiple prefix separated with ','`
CGenDaoBriefStdTime = `use time.Time from stdlib instead of gtime.Time for generated time/date fields of tables`
CGenDaoBriefWithTime = `add created time for auto produced go files`
CGenDaoBriefGJsonSupport = `use gJsonSupport to use *gjson.Json instead of string for generated json fields of tables`
CGenDaoBriefImportPrefix = `custom import prefix for generated go files`
CGenDaoBriefDaoPath = `directory path for storing generated dao files under path`
CGenDaoBriefDoPath = `directory path for storing generated do files under path`
CGenDaoBriefEntityPath = `directory path for storing generated entity files under path`
CGenDaoBriefOverwriteDao = `overwrite all dao files both inside/outside internal folder`
CGenDaoBriefModelFile = `custom file name for storing generated model content`
CGenDaoBriefModelFileForDao = `custom file name generating model for DAO operations like Where/Data. It's empty in default`
CGenDaoBriefDescriptionTag = `add comment to description tag for each field`
CGenDaoBriefNoJsonTag = `no json tag will be added for each field`
CGenDaoBriefNoModelComment = `no model comment will be added for each field`
CGenDaoBriefClear = `delete all generated go files that do not exist in database`
CGenDaoBriefTypeMapping = `custom local type mapping for generated struct attributes relevant to fields of table`
CGenDaoBriefGroup = `
specifying the configuration group name of database for generated ORM instance,
it's not necessary and the default value is "default"
`
@ -145,6 +146,7 @@ func init() {
`CGenDaoBriefTablesEx`: CGenDaoBriefTablesEx,
`CGenDaoBriefPrefix`: CGenDaoBriefPrefix,
`CGenDaoBriefRemovePrefix`: CGenDaoBriefRemovePrefix,
`CGenDaoBriefRemoveFieldPrefix`: CGenDaoBriefRemoveFieldPrefix,
`CGenDaoBriefStdTime`: CGenDaoBriefStdTime,
`CGenDaoBriefWithTime`: CGenDaoBriefWithTime,
`CGenDaoBriefDaoPath`: CGenDaoBriefDaoPath,
@ -180,6 +182,7 @@ type (
Group string `name:"group" short:"g" brief:"{CGenDaoBriefGroup}" d:"default"`
Prefix string `name:"prefix" short:"f" brief:"{CGenDaoBriefPrefix}"`
RemovePrefix string `name:"removePrefix" short:"r" brief:"{CGenDaoBriefRemovePrefix}"`
RemoveFieldPrefix string `name:"removeFieldPrefix" short:"rf" brief:"{CGenDaoBriefRemoveFieldPrefix}"`
JsonCase string `name:"jsonCase" short:"j" brief:"{CGenDaoBriefJsonCase}" d:"CamelLower"`
ImportPrefix string `name:"importPrefix" short:"i" brief:"{CGenDaoBriefImportPrefix}"`
DaoPath string `name:"daoPath" short:"d" brief:"{CGenDaoBriefDaoPath}" d:"dao"`

View File

@ -138,6 +138,7 @@ type generateDaoInternalInput struct {
func generateDaoInternal(in generateDaoInternalInput) {
path := filepath.FromSlash(gfile.Join(in.DirPathDaoInternal, in.FileName+".go"))
removeFieldPrefixArray := gstr.SplitAndTrim(in.RemoveFieldPrefix, ",")
modelContent := gstr.ReplaceByMap(
getTemplateFromPathOrDefault(in.TplDaoInternalPath, consts.TemplateGenDaoInternalContent),
g.MapStrStr{
@ -146,8 +147,8 @@ func generateDaoInternal(in generateDaoInternalInput) {
tplVarGroupName: in.Group,
tplVarTableNameCamelCase: in.TableNameCamelCase,
tplVarTableNameCamelLowerCase: in.TableNameCamelLowerCase,
tplVarColumnDefine: gstr.Trim(generateColumnDefinitionForDao(in.FieldMap)),
tplVarColumnNames: gstr.Trim(generateColumnNamesForDao(in.FieldMap)),
tplVarColumnDefine: gstr.Trim(generateColumnDefinitionForDao(in.FieldMap, removeFieldPrefixArray)),
tplVarColumnNames: gstr.Trim(generateColumnNamesForDao(in.FieldMap, removeFieldPrefixArray)),
})
modelContent = replaceDefaultVar(in.CGenDaoInternalInput, modelContent)
if err := gfile.PutContents(path, strings.TrimSpace(modelContent)); err != nil {
@ -160,16 +161,23 @@ func generateDaoInternal(in generateDaoInternalInput) {
// generateColumnNamesForDao generates and returns the column names assignment content of column struct
// for specified table.
func generateColumnNamesForDao(fieldMap map[string]*gdb.TableField) string {
func generateColumnNamesForDao(fieldMap map[string]*gdb.TableField, removeFieldPrefixArray []string) string {
var (
buffer = bytes.NewBuffer(nil)
array = make([][]string, len(fieldMap))
names = sortFieldKeyForDao(fieldMap)
)
for index, name := range names {
field := fieldMap[name]
newFiledName := field.Name
for _, v := range removeFieldPrefixArray {
newFiledName = gstr.TrimLeftStr(newFiledName, v, 1)
}
array[index] = []string{
" #" + gstr.CaseCamel(field.Name) + ":",
" #" + gstr.CaseCamel(newFiledName) + ":",
fmt.Sprintf(` #"%s",`, field.Name),
}
}
@ -189,12 +197,13 @@ func generateColumnNamesForDao(fieldMap map[string]*gdb.TableField) string {
}
// generateColumnDefinitionForDao generates and returns the column names definition for specified table.
func generateColumnDefinitionForDao(fieldMap map[string]*gdb.TableField) string {
func generateColumnDefinitionForDao(fieldMap map[string]*gdb.TableField, removeFieldPrefixArray []string) string {
var (
buffer = bytes.NewBuffer(nil)
array = make([][]string, len(fieldMap))
names = sortFieldKeyForDao(fieldMap)
)
for index, name := range names {
var (
field = fieldMap[name]
@ -203,8 +212,12 @@ func generateColumnDefinitionForDao(fieldMap map[string]*gdb.TableField) string
"\r", " ",
}))
)
newFiledName := field.Name
for _, v := range removeFieldPrefixArray {
newFiledName = gstr.TrimLeftStr(newFiledName, v, 1)
}
array[index] = []string{
" #" + gstr.CaseCamel(field.Name),
" #" + gstr.CaseCamel(newFiledName),
" # " + "string",
" #" + fmt.Sprintf(`// %s`, comment),
}

View File

@ -126,8 +126,13 @@ func generateStructFieldDefinition(
tagKey = "`"
descriptionTag = gstr.Replace(formatComment(field.Comment), `"`, `\"`)
)
removeFieldPrefixArray := gstr.SplitAndTrim(in.RemoveFieldPrefix, ",")
newFiledName := field.Name
for _, v := range removeFieldPrefixArray {
newFiledName = gstr.TrimLeftStr(newFiledName, v, 1)
}
attrLines = []string{
" #" + gstr.CaseCamel(field.Name),
" #" + gstr.CaseCamel(newFiledName),
" #" + localTypeNameStr,
}
attrLines = append(attrLines, " #"+fmt.Sprintf(tagKey+`json:"%s"`, jsonTag))

View File

@ -31,16 +31,17 @@ import (
type (
CGenPbEntity struct{}
CGenPbEntityInput struct {
g.Meta `name:"pbentity" config:"{CGenPbEntityConfig}" brief:"{CGenPbEntityBrief}" eg:"{CGenPbEntityEg}" ad:"{CGenPbEntityAd}"`
Path string `name:"path" short:"p" brief:"{CGenPbEntityBriefPath}" d:"manifest/protobuf/pbentity"`
Package string `name:"package" short:"k" brief:"{CGenPbEntityBriefPackage}"`
Link string `name:"link" short:"l" brief:"{CGenPbEntityBriefLink}"`
Tables string `name:"tables" short:"t" brief:"{CGenPbEntityBriefTables}"`
Prefix string `name:"prefix" short:"f" brief:"{CGenPbEntityBriefPrefix}"`
RemovePrefix string `name:"removePrefix" short:"r" brief:"{CGenPbEntityBriefRemovePrefix}"`
NameCase string `name:"nameCase" short:"n" brief:"{CGenPbEntityBriefNameCase}" d:"Camel"`
JsonCase string `name:"jsonCase" short:"j" brief:"{CGenPbEntityBriefJsonCase}" d:"CamelLower"`
Option string `name:"option" short:"o" brief:"{CGenPbEntityBriefOption}"`
g.Meta `name:"pbentity" config:"{CGenPbEntityConfig}" brief:"{CGenPbEntityBrief}" eg:"{CGenPbEntityEg}" ad:"{CGenPbEntityAd}"`
Path string `name:"path" short:"p" brief:"{CGenPbEntityBriefPath}" d:"manifest/protobuf/pbentity"`
Package string `name:"package" short:"k" brief:"{CGenPbEntityBriefPackage}"`
Link string `name:"link" short:"l" brief:"{CGenPbEntityBriefLink}"`
Tables string `name:"tables" short:"t" brief:"{CGenPbEntityBriefTables}"`
Prefix string `name:"prefix" short:"f" brief:"{CGenPbEntityBriefPrefix}"`
RemovePrefix string `name:"removePrefix" short:"r" brief:"{CGenPbEntityBriefRemovePrefix}"`
RemoveFieldPrefix string `name:"removeFieldPrefix" short:"rf" brief:"{CGenPbEntityBriefRemoveFieldPrefix}"`
NameCase string `name:"nameCase" short:"n" brief:"{CGenPbEntityBriefNameCase}" d:"Camel"`
JsonCase string `name:"jsonCase" short:"j" brief:"{CGenPbEntityBriefJsonCase}" d:"CamelLower"`
Option string `name:"option" short:"o" brief:"{CGenPbEntityBriefOption}"`
}
CGenPbEntityOutput struct{}
@ -87,14 +88,15 @@ CONFIGURATION SUPPORT
option java_package = "protobuf/demos";
option php_namespace = "protobuf/demos";
`
CGenPbEntityBriefPath = `directory path for generated files storing`
CGenPbEntityBriefPackage = `package path for all entity proto files`
CGenPbEntityBriefLink = `database configuration, the same as the ORM configuration of GoFrame`
CGenPbEntityBriefTables = `generate models only for given tables, multiple table names separated with ','`
CGenPbEntityBriefPrefix = `add specified prefix for all entity names and entity proto files`
CGenPbEntityBriefRemovePrefix = `remove specified prefix of the table, multiple prefix separated with ','`
CGenPbEntityBriefOption = `extra protobuf options`
CGenPbEntityBriefGroup = `
CGenPbEntityBriefPath = `directory path for generated files storing`
CGenPbEntityBriefPackage = `package path for all entity proto files`
CGenPbEntityBriefLink = `database configuration, the same as the ORM configuration of GoFrame`
CGenPbEntityBriefTables = `generate models only for given tables, multiple table names separated with ','`
CGenPbEntityBriefPrefix = `add specified prefix for all entity names and entity proto files`
CGenPbEntityBriefRemovePrefix = `remove specified prefix of the table, multiple prefix separated with ','`
CGenPbEntityBriefRemoveFieldPrefix = `remove specified prefix of the field, multiple prefix separated with ','`
CGenPbEntityBriefOption = `extra protobuf options`
CGenPbEntityBriefGroup = `
specifying the configuration group name of database for generated ORM instance,
it's not necessary and the default value is "default"
`
@ -120,20 +122,21 @@ set it to "none" to ignore json tag generating.
func init() {
gtag.Sets(g.MapStrStr{
`CGenPbEntityConfig`: CGenPbEntityConfig,
`CGenPbEntityBrief`: CGenPbEntityBrief,
`CGenPbEntityEg`: CGenPbEntityEg,
`CGenPbEntityAd`: CGenPbEntityAd,
`CGenPbEntityBriefPath`: CGenPbEntityBriefPath,
`CGenPbEntityBriefPackage`: CGenPbEntityBriefPackage,
`CGenPbEntityBriefLink`: CGenPbEntityBriefLink,
`CGenPbEntityBriefTables`: CGenPbEntityBriefTables,
`CGenPbEntityBriefPrefix`: CGenPbEntityBriefPrefix,
`CGenPbEntityBriefRemovePrefix`: CGenPbEntityBriefRemovePrefix,
`CGenPbEntityBriefGroup`: CGenPbEntityBriefGroup,
`CGenPbEntityBriefNameCase`: CGenPbEntityBriefNameCase,
`CGenPbEntityBriefJsonCase`: CGenPbEntityBriefJsonCase,
`CGenPbEntityBriefOption`: CGenPbEntityBriefOption,
`CGenPbEntityConfig`: CGenPbEntityConfig,
`CGenPbEntityBrief`: CGenPbEntityBrief,
`CGenPbEntityEg`: CGenPbEntityEg,
`CGenPbEntityAd`: CGenPbEntityAd,
`CGenPbEntityBriefPath`: CGenPbEntityBriefPath,
`CGenPbEntityBriefPackage`: CGenPbEntityBriefPackage,
`CGenPbEntityBriefLink`: CGenPbEntityBriefLink,
`CGenPbEntityBriefTables`: CGenPbEntityBriefTables,
`CGenPbEntityBriefPrefix`: CGenPbEntityBriefPrefix,
`CGenPbEntityBriefRemovePrefix`: CGenPbEntityBriefRemovePrefix,
`CGenPbEntityBriefRemoveFieldPrefix`: CGenPbEntityBriefRemoveFieldPrefix,
`CGenPbEntityBriefGroup`: CGenPbEntityBriefGroup,
`CGenPbEntityBriefNameCase`: CGenPbEntityBriefNameCase,
`CGenPbEntityBriefJsonCase`: CGenPbEntityBriefJsonCase,
`CGenPbEntityBriefOption`: CGenPbEntityBriefOption,
})
}
@ -351,9 +354,16 @@ func generateMessageFieldForPbEntity(index int, field *gdb.TableField, in CGenPb
jsonTagStr = " " + jsonTagStr
}
}
removeFieldPrefixArray := gstr.SplitAndTrim(in.RemoveFieldPrefix, ",")
newFiledName := field.Name
for _, v := range removeFieldPrefixArray {
newFiledName = gstr.TrimLeftStr(newFiledName, v, 1)
}
return []string{
" #" + localTypeNameStr,
" #" + formatCase(field.Name, in.NameCase),
" #" + formatCase(newFiledName, in.NameCase),
" #= " + gconv.String(index) + jsonTagStr + ";",
" #" + fmt.Sprintf(`// %s`, comment),
}

View File

@ -24,15 +24,19 @@ var (
)
func init() {
logger.SetStack(false)
if genv.Get(headerPrintEnvName).String() == "1" {
logger.SetHeaderPrint(true)
} else {
logger.SetHeaderPrint(false)
}
if gcmd.GetOpt("debug") != nil || gcmd.GetOpt("gf.debug") != nil {
logger.SetHeaderPrint(true)
logger.SetStackSkip(4)
logger.SetFlags(logger.GetFlags() | glog.F_FILE_LONG)
logger.SetDebug(true)
} else {
logger.SetStack(false)
logger.SetDebug(false)
}
}

View File

@ -8,24 +8,27 @@ package gvar
import "github.com/gogf/gf/v2/util/gconv"
// MapOption specifies the option for map converting.
type MapOption = gconv.MapOption
// Map converts and returns `v` as map[string]interface{}.
func (v *Var) Map(tags ...string) map[string]interface{} {
return gconv.Map(v.Val(), tags...)
func (v *Var) Map(option ...MapOption) map[string]interface{} {
return gconv.Map(v.Val(), option...)
}
// MapStrAny is like function Map, but implements the interface of MapStrAny.
func (v *Var) MapStrAny() map[string]interface{} {
return v.Map()
func (v *Var) MapStrAny(option ...MapOption) map[string]interface{} {
return v.Map(option...)
}
// MapStrStr converts and returns `v` as map[string]string.
func (v *Var) MapStrStr(tags ...string) map[string]string {
return gconv.MapStrStr(v.Val(), tags...)
func (v *Var) MapStrStr(option ...MapOption) map[string]string {
return gconv.MapStrStr(v.Val(), option...)
}
// MapStrVar converts and returns `v` as map[string]Var.
func (v *Var) MapStrVar(tags ...string) map[string]*Var {
m := v.Map(tags...)
func (v *Var) MapStrVar(option ...MapOption) map[string]*Var {
m := v.Map(option...)
if len(m) > 0 {
vMap := make(map[string]*Var, len(m))
for k, v := range m {
@ -37,16 +40,19 @@ func (v *Var) MapStrVar(tags ...string) map[string]*Var {
}
// MapDeep converts and returns `v` as map[string]interface{} recursively.
// Deprecated: used Map instead.
func (v *Var) MapDeep(tags ...string) map[string]interface{} {
return gconv.MapDeep(v.Val(), tags...)
}
// MapStrStrDeep converts and returns `v` as map[string]string recursively.
// Deprecated: used MapStrStr instead.
func (v *Var) MapStrStrDeep(tags ...string) map[string]string {
return gconv.MapStrStrDeep(v.Val(), tags...)
}
// MapStrVarDeep converts and returns `v` as map[string]*Var recursively.
// Deprecated: used MapStrVar instead.
func (v *Var) MapStrVarDeep(tags ...string) map[string]*Var {
m := v.MapDeep(tags...)
if len(m) > 0 {
@ -61,12 +67,12 @@ func (v *Var) MapStrVarDeep(tags ...string) map[string]*Var {
// Maps converts and returns `v` as map[string]string.
// See gconv.Maps.
func (v *Var) Maps(tags ...string) []map[string]interface{} {
return gconv.Maps(v.Val(), tags...)
func (v *Var) Maps(option ...MapOption) []map[string]interface{} {
return gconv.Maps(v.Val(), option...)
}
// MapsDeep converts `value` to []map[string]interface{} recursively.
// See gconv.MapsDeep.
// Deprecated: used Maps instead.
func (v *Var) MapsDeep(tags ...string) []map[string]interface{} {
return gconv.MapsDeep(v.Val(), tags...)
}

View File

@ -4,7 +4,7 @@ go 1.18
require (
github.com/apolloconfig/agollo/v4 v4.3.1
github.com/gogf/gf/v2 v2.5.7
github.com/gogf/gf/v2 v2.6.0
)
require (

View File

@ -3,7 +3,7 @@ module github.com/gogf/gf/contrib/config/consul/v2
go 1.19
require (
github.com/gogf/gf/v2 v2.5.7
github.com/gogf/gf/v2 v2.6.0
github.com/hashicorp/consul/api v1.24.0
github.com/hashicorp/go-cleanhttp v0.5.2
)

View File

@ -3,7 +3,7 @@ module github.com/gogf/gf/contrib/config/kubecm/v2
go 1.19
require (
github.com/gogf/gf/v2 v2.5.7
github.com/gogf/gf/v2 v2.6.0
k8s.io/api v0.27.4
k8s.io/apimachinery v0.27.4
k8s.io/client-go v0.27.4

View File

@ -3,7 +3,7 @@ module github.com/gogf/gf/contrib/config/nacos/v2
go 1.18
require (
github.com/gogf/gf/v2 v2.5.7
github.com/gogf/gf/v2 v2.6.0
github.com/nacos-group/nacos-sdk-go v1.1.4
)

View File

@ -3,7 +3,7 @@ module github.com/gogf/gf/contrib/config/polaris/v2
go 1.18
require (
github.com/gogf/gf/v2 v2.5.7
github.com/gogf/gf/v2 v2.6.0
github.com/polarismesh/polaris-go v1.5.5
)

View File

@ -4,7 +4,7 @@ go 1.18
require (
github.com/ClickHouse/clickhouse-go/v2 v2.0.15
github.com/gogf/gf/v2 v2.5.7
github.com/gogf/gf/v2 v2.6.0
github.com/google/uuid v1.3.0
github.com/shopspring/decimal v1.3.1
)

View File

@ -6,7 +6,7 @@ replace github.com/gogf/gf/v2 => ../../../
require (
gitee.com/chunanyong/dm v1.8.12
github.com/gogf/gf/v2 v2.5.7
github.com/gogf/gf/v2 v2.6.0
)
require (

View File

@ -4,7 +4,7 @@ go 1.18
require (
github.com/denisenkom/go-mssqldb v0.12.3
github.com/gogf/gf/v2 v2.5.7
github.com/gogf/gf/v2 v2.6.0
)
require (

View File

@ -4,7 +4,7 @@ go 1.18
require (
github.com/go-sql-driver/mysql v1.7.1
github.com/gogf/gf/v2 v2.5.7
github.com/gogf/gf/v2 v2.6.0
)
require (

View File

@ -881,3 +881,28 @@ func Test_Issue3086(t *testing.T) {
t.Assert(n, 2)
})
}
// https://github.com/gogf/gf/issues/3204
func Test_Issue3204(t *testing.T) {
table := createInitTable()
defer dropTable(table)
db.SetDebug(true)
gtest.C(t, func(t *gtest.T) {
type User struct {
g.Meta `orm:"do:true"`
Id interface{} `orm:"id,omitempty"`
Passport interface{} `orm:"passport,omitempty"`
Password interface{} `orm:"password,omitempty"`
Nickname interface{} `orm:"nickname,omitempty"`
CreateTime interface{} `orm:"create_time,omitempty"`
}
where := User{
Id: 2,
Passport: "",
}
all, err := db.Model(table).Where(where).All()
t.AssertNil(err)
t.Assert(len(all), 1)
t.Assert(all[0]["id"], 2)
})
}

View File

@ -3,7 +3,7 @@ module github.com/gogf/gf/contrib/drivers/oracle/v2
go 1.18
require (
github.com/gogf/gf/v2 v2.5.7
github.com/gogf/gf/v2 v2.6.0
github.com/sijms/go-ora/v2 v2.7.10
)

View File

@ -3,7 +3,7 @@ module github.com/gogf/gf/contrib/drivers/pgsql/v2
go 1.18
require (
github.com/gogf/gf/v2 v2.5.7
github.com/gogf/gf/v2 v2.6.0
github.com/lib/pq v1.10.9
)

View File

@ -15,6 +15,7 @@ import (
"context"
"database/sql"
"fmt"
"regexp"
"strings"
_ "github.com/lib/pq"
@ -237,6 +238,12 @@ func (d *Driver) Tables(ctx context.Context, schema ...string) (tables []string,
if err != nil {
return nil, err
}
useRelpartbound := ""
if gstr.CompareVersion(d.version(ctx, link), "10") >= 0 {
useRelpartbound = "AND c.relpartbound IS NULL"
}
var query = fmt.Sprintf(`
SELECT
c.relname
@ -247,10 +254,11 @@ INNER JOIN pg_namespace n ON
WHERE
n.nspname = '%s'
AND c.relkind IN ('r', 'p')
AND c.relpartbound IS NULL
%s
ORDER BY
c.relname`,
usedSchema,
useRelpartbound,
)
query, _ = gregex.ReplaceString(`[\n\r\s]+`, " ", gstr.Trim(query))
@ -266,6 +274,23 @@ ORDER BY
return
}
// version checks and returns the database version.
func (d *Driver) version(ctx context.Context, link gdb.Link) string {
result, err := d.DoSelect(ctx, link, "SELECT version();")
if err != nil {
return ""
}
if len(result) > 0 {
if v, ok := result[0]["version"]; ok {
matches := regexp.MustCompile(`PostgreSQL (\d+\.\d+)`).FindStringSubmatch(v.String())
if len(matches) >= 2 {
return matches[1]
}
}
}
return ""
}
// TableFields retrieves and returns the fields' information of specified table of current schema.
func (d *Driver) TableFields(ctx context.Context, table string, schema ...string) (fields map[string]*gdb.TableField, err error) {
var (

View File

@ -4,7 +4,7 @@ go 1.18
require (
github.com/glebarez/go-sqlite v1.21.2
github.com/gogf/gf/v2 v2.5.7
github.com/gogf/gf/v2 v2.6.0
)
require (

View File

@ -3,7 +3,7 @@ module github.com/gogf/gf/contrib/drivers/sqlitecgo/v2
go 1.18
require (
github.com/gogf/gf/v2 v2.5.7
github.com/gogf/gf/v2 v2.6.0
github.com/mattn/go-sqlite3 v1.14.17
)

View File

@ -3,7 +3,7 @@ module github.com/gogf/gf/contrib/nosql/redis/v2
go 1.18
require (
github.com/gogf/gf/v2 v2.5.7
github.com/gogf/gf/v2 v2.6.0
github.com/redis/go-redis/v9 v9.2.1
go.opentelemetry.io/otel v1.14.0
go.opentelemetry.io/otel/trace v1.14.0

View File

@ -3,7 +3,7 @@ module github.com/gogf/gf/contrib/registry/etcd/v2
go 1.18
require (
github.com/gogf/gf/v2 v2.5.7
github.com/gogf/gf/v2 v2.6.0
go.etcd.io/etcd/client/v3 v3.5.7
)

View File

@ -2,7 +2,7 @@ module github.com/gogf/gf/contrib/registry/file/v2
go 1.18
require github.com/gogf/gf/v2 v2.5.7
require github.com/gogf/gf/v2 v2.6.0
require (
github.com/BurntSushi/toml v1.2.0 // indirect

View File

@ -3,7 +3,7 @@ module github.com/gogf/gf/contrib/registry/nacos/v2
go 1.18
require (
github.com/gogf/gf/v2 v2.5.7
github.com/gogf/gf/v2 v2.6.0
github.com/joy999/nacos-sdk-go v0.0.0-20231120071639-10a34b3e7288
)

View File

@ -3,7 +3,7 @@ module github.com/gogf/gf/contrib/registry/polaris/v2
go 1.18
require (
github.com/gogf/gf/v2 v2.5.7
github.com/gogf/gf/v2 v2.6.0
github.com/polarismesh/polaris-go v1.5.5
)

View File

@ -4,7 +4,7 @@ go 1.18
require (
github.com/go-zookeeper/zk v1.0.3
github.com/gogf/gf/v2 v2.5.7
github.com/gogf/gf/v2 v2.6.0
golang.org/x/sync v0.4.0
)

View File

@ -3,8 +3,8 @@ module github.com/gogf/gf/contrib/rpc/grpcx/v2
go 1.18
require (
github.com/gogf/gf/contrib/registry/file/v2 v2.5.7
github.com/gogf/gf/v2 v2.5.7
github.com/gogf/gf/contrib/registry/file/v2 v2.6.0
github.com/gogf/gf/v2 v2.6.0
go.opentelemetry.io/otel v1.14.0
go.opentelemetry.io/otel/trace v1.14.0
google.golang.org/grpc v1.57.2

View File

@ -8,7 +8,6 @@ package grpcx
import (
"context"
"google.golang.org/grpc"
"github.com/gogf/gf/v2/frame/g"
@ -18,18 +17,41 @@ import (
// GrpcServerConfig is the configuration for server.
type GrpcServerConfig struct {
Address string // (optional) Single address for server listening, use `:0` or `ip:0` to serve random port.
Name string // (optional) Name for current service.
Logger *glog.Logger // (optional) Logger for server.
LogPath string // (optional) LogPath specifies the directory for storing logging files.
LogStdout bool // (optional) LogStdout specifies whether printing logging content to stdout.
ErrorStack bool // (optional) ErrorStack specifies whether logging stack information when error.
ErrorLogEnabled bool // (optional) ErrorLogEnabled enables error logging content to files.
ErrorLogPattern string // (optional) ErrorLogPattern specifies the error log file pattern like: error-{Ymd}.log
AccessLogEnabled bool // (optional) AccessLogEnabled enables access logging content to file.
AccessLogPattern string // (optional) AccessLogPattern specifies the error log file pattern like: access-{Ymd}.log
Endpoints []string // (optional) Endpoints are custom endpoints for service register, it uses Address if empty.
Options []grpc.ServerOption // (optional) GRPC Server options.
// (optional) Name for current service.
Name string
// (optional) Single address for server listening, use `:0` or `ip:0` to serve random port.
Address string
// (optional) Logger for server.
Logger *glog.Logger
// (optional) LogPath specifies the directory for storing logging files.
LogPath string
// (optional) LogStdout specifies whether printing logging content to stdout.
LogStdout bool
// (optional) ErrorStack specifies whether logging stack information when error.
ErrorStack bool
// (optional) ErrorLogEnabled enables error logging content to files.
ErrorLogEnabled bool
// (optional) ErrorLogPattern specifies the error log file pattern like: error-{Ymd}.log
ErrorLogPattern string
// (optional) AccessLogEnabled enables access logging content to file.
AccessLogEnabled bool
// (optional) AccessLogPattern specifies the error log file pattern like: access-{Ymd}.log
AccessLogPattern string
// (optional) Endpoints are custom endpoints for service register, it uses Address if empty.
Endpoints []string
// (optional) GRPC Server options.
Options []grpc.ServerOption
}
// NewConfig creates and returns a ServerConfig object with default configurations.
@ -51,6 +73,7 @@ func (s modServer) NewConfig() *GrpcServerConfig {
)
// Reading configuration file and updating the configured keys.
if g.Cfg().Available(ctx) {
// Server attributes configuration.
if err = g.Cfg().MustGet(ctx, configNodeNameGrpcServer).Struct(&config); err != nil {
g.Log().Error(ctx, err)
}

View File

@ -2,7 +2,7 @@ module github.com/gogf/gf/contrib/sdk/httpclient/v2
go 1.18
require github.com/gogf/gf/v2 v2.5.7
require github.com/gogf/gf/v2 v2.6.0
require (
github.com/BurntSushi/toml v1.2.0 // indirect

View File

@ -3,7 +3,7 @@ module github.com/gogf/gf/contrib/trace/jaeger/v2
go 1.18
require (
github.com/gogf/gf/v2 v2.5.7
github.com/gogf/gf/v2 v2.6.0
go.opentelemetry.io/otel v1.14.0
go.opentelemetry.io/otel/exporters/jaeger v1.14.0
go.opentelemetry.io/otel/sdk v1.14.0

View File

@ -3,7 +3,7 @@ module github.com/gogf/gf/contrib/trace/otlpgrpc/v2
go 1.20
require (
github.com/gogf/gf/v2 v2.5.7
github.com/gogf/gf/v2 v2.6.0
go.opentelemetry.io/otel v1.19.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0

View File

@ -3,7 +3,7 @@ module github.com/gogf/gf/contrib/trace/otlphttp/v2
go 1.20
require (
github.com/gogf/gf/v2 v2.5.7
github.com/gogf/gf/v2 v2.6.0
go.opentelemetry.io/otel v1.19.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0

View File

@ -60,7 +60,7 @@ func (c *Core) GetFieldType(ctx context.Context, fieldName, table, schema string
func (c *Core) ConvertDataForRecord(ctx context.Context, value interface{}, table string) (map[string]interface{}, error) {
var (
err error
data = DataToMapDeep(value)
data = MapOrStructToMapDeep(value, false)
)
for fieldName, fieldValue := range data {
data[fieldName], err = c.db.ConvertValueForField(

View File

@ -210,14 +210,22 @@ func GetInsertOperationByOption(option InsertOption) string {
}
func anyValueToMapBeforeToRecord(value interface{}) map[string]interface{} {
return gconv.Map(value, structTagPriority...)
return gconv.Map(value, gconv.MapOption{Tags: structTagPriority})
}
// DataToMapDeep converts `value` to map type recursively(if attribute struct is embedded).
// DaToMapDeep is deprecated, use MapOrStructToMapDeep instead.
func DaToMapDeep(value interface{}) map[string]interface{} {
return MapOrStructToMapDeep(value, false)
}
// MapOrStructToMapDeep converts `value` to map type recursively(if attribute struct is embedded).
// The parameter `value` should be type of *map/map/*struct/struct.
// It supports embedded struct definition for struct.
func DataToMapDeep(value interface{}) map[string]interface{} {
m := gconv.Map(value, structTagPriority...)
func MapOrStructToMapDeep(value interface{}, omitempty bool) map[string]interface{} {
m := gconv.Map(value, gconv.MapOption{
Tags: structTagPriority,
OmitEmpty: omitempty,
})
for k, v := range m {
switch v.(type) {
case time.Time, *time.Time, gtime.Time, *gtime.Time, gjson.Json, *gjson.Json:
@ -413,7 +421,7 @@ func formatWhereHolder(ctx context.Context, db DB, in formatWhereHolderInput) (n
newArgs = formatWhereInterfaces(db, gconv.Interfaces(in.Where), buffer, newArgs)
case reflect.Map:
for key, value := range DataToMapDeep(in.Where) {
for key, value := range MapOrStructToMapDeep(in.Where, true) {
if in.OmitNil && empty.IsNil(value) {
continue
}
@ -468,7 +476,7 @@ func formatWhereHolder(ctx context.Context, db DB, in formatWhereHolderInput) (n
var (
reflectType = reflectInfo.OriginValue.Type()
structField reflect.StructField
data = DataToMapDeep(in.Where)
data = MapOrStructToMapDeep(in.Where, true)
)
// If `Prefix` is given, it checks and retrieves the table name.
if in.Prefix != "" {

View File

@ -268,7 +268,7 @@ func (m *Model) doInsertWithOption(ctx context.Context, insertOption InsertOptio
default:
// It uses gconv.Map here to simply fo the type converting from interface{} to map[string]interface{},
// as there's another DataToMapDeep in next logic to do the deep converting.
// as there's another MapOrStructToMapDeep in next logic to do the deep converting.
reflectInfo := reflection.OriginValueAndKind(newData)
switch reflectInfo.OriginKind {
// If it's slice type, it then converts it to List type.

View File

@ -16,9 +16,9 @@ type Option struct {
Code gcode.Code // Error code if necessary.
}
// NewOption creates and returns a custom error with Option.
// NewWithOption creates and returns a custom error with Option.
// It is the senior usage for creating error, which is often used internally in framework.
func NewOption(option Option) error {
func NewWithOption(option Option) error {
err := &Error{
error: option.Error,
text: option.Text,
@ -29,3 +29,9 @@ func NewOption(option Option) error {
}
return err
}
// NewOption creates and returns a custom error with Option.
// Deprecated: use NewWithOption instead.
func NewOption(option Option) error {
return NewWithOption(option)
}

View File

@ -442,7 +442,7 @@ func Test_HashCode(t *testing.T) {
func Test_NewOption(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.AssertNE(gerror.NewOption(gerror.Option{
t.AssertNE(gerror.NewWithOption(gerror.Option{
Error: errors.New("NewOptionError"),
Stack: true,
Text: "Text",

View File

@ -3,21 +3,21 @@ module github.com/gogf/gf/example
go 1.20
require (
github.com/gogf/gf/contrib/config/apollo/v2 v2.5.7
github.com/gogf/gf/contrib/config/consul/v2 v2.5.7
github.com/gogf/gf/contrib/config/kubecm/v2 v2.5.7
github.com/gogf/gf/contrib/config/nacos/v2 v2.5.7
github.com/gogf/gf/contrib/config/polaris/v2 v2.5.7
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.5.7
github.com/gogf/gf/contrib/nosql/redis/v2 v2.5.7
github.com/gogf/gf/contrib/registry/etcd/v2 v2.5.7
github.com/gogf/gf/contrib/registry/file/v2 v2.5.7
github.com/gogf/gf/contrib/config/apollo/v2 v2.6.0
github.com/gogf/gf/contrib/config/consul/v2 v2.6.0
github.com/gogf/gf/contrib/config/kubecm/v2 v2.6.0
github.com/gogf/gf/contrib/config/nacos/v2 v2.6.0
github.com/gogf/gf/contrib/config/polaris/v2 v2.6.0
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.6.0
github.com/gogf/gf/contrib/nosql/redis/v2 v2.6.0
github.com/gogf/gf/contrib/registry/etcd/v2 v2.6.0
github.com/gogf/gf/contrib/registry/file/v2 v2.6.0
github.com/gogf/gf/contrib/registry/nacos/v2 v2.5.6
github.com/gogf/gf/contrib/registry/polaris/v2 v2.5.7
github.com/gogf/gf/contrib/rpc/grpcx/v2 v2.5.7
github.com/gogf/gf/contrib/trace/otlpgrpc/v2 v2.5.7
github.com/gogf/gf/contrib/trace/otlphttp/v2 v2.5.7
github.com/gogf/gf/v2 v2.5.7
github.com/gogf/gf/contrib/registry/polaris/v2 v2.6.0
github.com/gogf/gf/contrib/rpc/grpcx/v2 v2.6.0
github.com/gogf/gf/contrib/trace/otlpgrpc/v2 v2.6.0
github.com/gogf/gf/contrib/trace/otlphttp/v2 v2.6.0
github.com/gogf/gf/v2 v2.6.0
github.com/hashicorp/consul/api v1.24.0
github.com/hashicorp/go-cleanhttp v0.5.2
github.com/nacos-group/nacos-sdk-go v1.1.4

View File

@ -338,8 +338,8 @@ func (c *Client) callRequest(req *http.Request) (resp *Response, err error) {
// raw HTTP request-response procedure.
reqBodyContent, _ := io.ReadAll(req.Body)
resp.requestBody = reqBodyContent
req.Body = utils.NewReadCloser(reqBodyContent, false)
for {
req.Body = utils.NewReadCloser(reqBodyContent, false)
if resp.Response, err = c.Do(req); err != nil {
err = gerror.Wrapf(err, `request failed`)
// The response might not be nil when err != nil.

View File

@ -205,7 +205,7 @@ var (
)
var (
ErrNeedJsonBody = gerror.NewOption(gerror.Option{
ErrNeedJsonBody = gerror.NewWithOption(gerror.Option{
Text: "the request body content should be JSON format",
Code: gcode.CodeInvalidRequest,
})

View File

@ -117,7 +117,7 @@ func forkReloadProcess(ctx context.Context, newExeFilePath ...string) error {
var (
path = os.Args[0]
)
if len(newExeFilePath) > 0 {
if len(newExeFilePath) > 0 && newExeFilePath[0] != "" {
path = newExeFilePath[0]
}
var (
@ -156,12 +156,12 @@ func forkReloadProcess(ctx context.Context, newExeFilePath ...string) error {
}
// forkRestartProcess creates a new server process.
func forkRestartProcess(ctx context.Context, newExeFilePath string) error {
func forkRestartProcess(ctx context.Context, newExeFilePath ...string) error {
var (
path = os.Args[0]
)
if newExeFilePath != "" {
path = newExeFilePath
if len(newExeFilePath) > 0 && newExeFilePath[0] != "" {
path = newExeFilePath[0]
}
if err := os.Unsetenv(adminActionReloadEnvKey); err != nil {
intlog.Errorf(ctx, `%+v`, err)

View File

@ -11,6 +11,7 @@ import (
"os"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcfg"
"github.com/gogf/gf/v2/os/gcmd"
"github.com/gogf/gf/v2/os/gctx"
"github.com/gogf/gf/v2/os/genv"
@ -64,3 +65,21 @@ func ExampleConfig_GetWithCmd() {
// cmd:
// cmd:yes
}
func Example_NewWithAdapter() {
var (
ctx = gctx.New()
content = `{"a":"b", "c":1}`
adapter, err = gcfg.NewAdapterContent(content)
)
if err != nil {
panic(err)
}
config := gcfg.NewWithAdapter(adapter)
fmt.Println(config.MustGet(ctx, "a"))
fmt.Println(config.MustGet(ctx, "c"))
// Output:
// b
// 1
}

View File

@ -219,8 +219,8 @@ func (l *Logger) print(ctx context.Context, level int, stack string, values ...a
}
}
// doDefaultPrint outputs the logging content according configuration.
func (l *Logger) doDefaultPrint(ctx context.Context, input *HandlerInput) *bytes.Buffer {
// doFinalPrint outputs the logging content according configuration.
func (l *Logger) doFinalPrint(ctx context.Context, input *HandlerInput) *bytes.Buffer {
var buffer *bytes.Buffer
// Allow output to stdout?
if l.config.StdoutPrint {

View File

@ -49,7 +49,7 @@ var defaultHandler Handler
// doFinalPrint is a handler for logging content printing.
// This handler outputs logging content to file/stdout/write if any of them configured.
func doFinalPrint(ctx context.Context, in *HandlerInput) {
buffer := in.Logger.doDefaultPrint(ctx, in)
buffer := in.Logger.doFinalPrint(ctx, in)
if in.Buffer.Len() == 0 {
in.Buffer = buffer
}

View File

@ -15,7 +15,7 @@ import (
var (
// ErrorDisabled is used for marking certain interface function not used.
ErrorDisabled = gerror.NewOption(gerror.Option{
ErrorDisabled = gerror.NewWithOption(gerror.Option{
Text: "this feature is disabled in this storage",
Code: gcode.CodeNotSupported,
})

View File

@ -22,40 +22,57 @@ const (
recursiveTypeTrue recursiveType = "true"
)
// MapOption specifies the option for map converting.
type MapOption struct {
// Deep marks doing Map function recursively, which means if the attribute of given converting value
// is also a struct/*struct, it automatically calls Map function on this attribute converting it to
// a map[string]interface{} type variable.
Deep bool
// OmitEmpty ignores the attributes that has json omitempty tag.
OmitEmpty bool
// Tags specifies the converted map key name by struct tag name.
Tags []string
}
// Map converts any variable `value` to map[string]interface{}. If the parameter `value` is not a
// map/struct/*struct type, then the conversion will fail and returns nil.
//
// If `value` is a struct/*struct object, the second parameter `tags` specifies the most priority
// tags that will be detected, otherwise it detects the tags in order of:
// gconv, json, field name.
func Map(value interface{}, tags ...string) map[string]interface{} {
return doMapConvert(value, recursiveTypeAuto, false, tags...)
func Map(value interface{}, option ...MapOption) map[string]interface{} {
return doMapConvert(value, recursiveTypeAuto, false, option...)
}
// MapDeep does Map function recursively, which means if the attribute of `value`
// is also a struct/*struct, calls Map function on this attribute converting it to
// a map[string]interface{} type variable.
// Also see Map.
// Deprecated: used Map instead.
func MapDeep(value interface{}, tags ...string) map[string]interface{} {
return doMapConvert(value, recursiveTypeTrue, false, tags...)
return doMapConvert(value, recursiveTypeTrue, false, MapOption{
Tags: tags,
})
}
// doMapConvert implements the map converting.
// It automatically checks and converts json string to map if `value` is string/[]byte.
//
// TODO completely implement the recursive converting for all types, especially the map.
func doMapConvert(value interface{}, recursive recursiveType, mustMapReturn bool, tags ...string) map[string]interface{} {
func doMapConvert(value interface{}, recursive recursiveType, mustMapReturn bool, option ...MapOption) map[string]interface{} {
if value == nil {
return nil
}
var usedOption = getUsedMapOption(option...)
newTags := StructTagPriority
switch len(tags) {
switch len(usedOption.Tags) {
case 0:
// No need handling.
case 1:
newTags = append(strings.Split(tags[0], ","), StructTagPriority...)
newTags = append(strings.Split(usedOption.Tags[0], ","), StructTagPriority...)
default:
newTags = append(tags, StructTagPriority...)
newTags = append(usedOption.Tags, StructTagPriority...)
}
// Assert the common combination of types, and finally it uses reflection.
dataMap := make(map[string]interface{})
@ -79,6 +96,8 @@ func doMapConvert(value interface{}, recursive recursiveType, mustMapReturn bool
return nil
}
case map[interface{}]interface{}:
recursiveOption := usedOption
recursiveOption.Tags = newTags
for k, v := range r {
dataMap[String(k)] = doMapConvertForMapOrStructValue(
doMapConvertForMapOrStructValueInput{
@ -86,7 +105,7 @@ func doMapConvert(value interface{}, recursive recursiveType, mustMapReturn bool
Value: v,
RecursiveType: recursive,
RecursiveOption: recursive == recursiveTypeTrue,
Tags: newTags,
Option: recursiveOption,
},
)
}
@ -136,6 +155,8 @@ func doMapConvert(value interface{}, recursive recursiveType, mustMapReturn bool
}
case map[string]interface{}:
if recursive == recursiveTypeTrue {
recursiveOption := usedOption
recursiveOption.Tags = newTags
// A copy of current map.
for k, v := range r {
dataMap[k] = doMapConvertForMapOrStructValue(
@ -144,7 +165,7 @@ func doMapConvert(value interface{}, recursive recursiveType, mustMapReturn bool
Value: v,
RecursiveType: recursive,
RecursiveOption: recursive == recursiveTypeTrue,
Tags: newTags,
Option: recursiveOption,
},
)
}
@ -153,6 +174,8 @@ func doMapConvert(value interface{}, recursive recursiveType, mustMapReturn bool
return r
}
case map[int]interface{}:
recursiveOption := usedOption
recursiveOption.Tags = newTags
for k, v := range r {
dataMap[String(k)] = doMapConvertForMapOrStructValue(
doMapConvertForMapOrStructValueInput{
@ -160,7 +183,7 @@ func doMapConvert(value interface{}, recursive recursiveType, mustMapReturn bool
Value: v,
RecursiveType: recursive,
RecursiveOption: recursive == recursiveTypeTrue,
Tags: newTags,
Option: recursiveOption,
},
)
}
@ -202,13 +225,15 @@ func doMapConvert(value interface{}, recursive recursiveType, mustMapReturn bool
}
}
case reflect.Map, reflect.Struct, reflect.Interface:
recursiveOption := usedOption
recursiveOption.Tags = newTags
convertedValue := doMapConvertForMapOrStructValue(
doMapConvertForMapOrStructValueInput{
IsRoot: true,
Value: value,
RecursiveType: recursive,
RecursiveOption: recursive == recursiveTypeTrue,
Tags: newTags,
Option: recursiveOption,
MustMapReturn: mustMapReturn,
},
)
@ -223,12 +248,20 @@ func doMapConvert(value interface{}, recursive recursiveType, mustMapReturn bool
return dataMap
}
func getUsedMapOption(option ...MapOption) MapOption {
var usedOption MapOption
if len(option) > 0 {
usedOption = option[0]
}
return usedOption
}
type doMapConvertForMapOrStructValueInput struct {
IsRoot bool // It returns directly if it is not root and with no recursive converting.
Value interface{} // Current operation value.
RecursiveType recursiveType // The type from top function entry.
RecursiveOption bool // Whether convert recursively for `current` operation.
Tags []string // Map key mapping.
Option MapOption // Map converting option.
MustMapReturn bool // Must return map instead of Value when empty.
}
@ -280,7 +313,7 @@ func doMapConvertForMapOrStructValue(in doMapConvertForMapOrStructValueInput) in
Value: mapValue,
RecursiveType: in.RecursiveType,
RecursiveOption: in.RecursiveType == recursiveTypeTrue,
Tags: in.Tags,
Option: in.Option,
},
)
}
@ -299,7 +332,7 @@ func doMapConvertForMapOrStructValue(in doMapConvertForMapOrStructValueInput) in
Value: mapV,
RecursiveType: in.RecursiveType,
RecursiveOption: in.RecursiveType == recursiveTypeTrue,
Tags: in.Tags,
Option: in.Option,
},
)
} else {
@ -327,7 +360,7 @@ func doMapConvertForMapOrStructValue(in doMapConvertForMapOrStructValueInput) in
}
mapKey = ""
fieldTag := rtField.Tag
for _, tag := range in.Tags {
for _, tag := range in.Option.Tags {
if mapKey = fieldTag.Get(tag); mapKey != "" {
break
}
@ -344,7 +377,7 @@ func doMapConvertForMapOrStructValue(in doMapConvertForMapOrStructValueInput) in
if len(array) > 1 {
switch strings.TrimSpace(array[1]) {
case "omitempty":
if empty.IsEmpty(rvField.Interface()) {
if in.Option.OmitEmpty && empty.IsEmpty(rvField.Interface()) {
continue
} else {
mapKey = strings.TrimSpace(array[0])
@ -389,7 +422,7 @@ func doMapConvertForMapOrStructValue(in doMapConvertForMapOrStructValueInput) in
Value: rvInterface,
RecursiveType: in.RecursiveType,
RecursiveOption: true,
Tags: in.Tags,
Option: in.Option,
})
if m, ok := anonymousValue.(map[string]interface{}); ok {
for k, v := range m {
@ -406,7 +439,7 @@ func doMapConvertForMapOrStructValue(in doMapConvertForMapOrStructValueInput) in
Value: rvInterface,
RecursiveType: in.RecursiveType,
RecursiveOption: true,
Tags: in.Tags,
Option: in.Option,
})
default:
@ -415,7 +448,7 @@ func doMapConvertForMapOrStructValue(in doMapConvertForMapOrStructValueInput) in
Value: rvInterface,
RecursiveType: in.RecursiveType,
RecursiveOption: in.RecursiveType == recursiveTypeTrue,
Tags: in.Tags,
Option: in.Option,
})
}
@ -434,7 +467,7 @@ func doMapConvertForMapOrStructValue(in doMapConvertForMapOrStructValueInput) in
Value: rvAttrField.Index(arrayIndex).Interface(),
RecursiveType: in.RecursiveType,
RecursiveOption: in.RecursiveType == recursiveTypeTrue,
Tags: in.Tags,
Option: in.Option,
},
)
}
@ -451,7 +484,7 @@ func doMapConvertForMapOrStructValue(in doMapConvertForMapOrStructValueInput) in
Value: rvAttrField.MapIndex(k).Interface(),
RecursiveType: in.RecursiveType,
RecursiveOption: in.RecursiveType == recursiveTypeTrue,
Tags: in.Tags,
Option: in.Option,
},
)
}
@ -490,7 +523,7 @@ func doMapConvertForMapOrStructValue(in doMapConvertForMapOrStructValueInput) in
Value: reflectValue.Index(i).Interface(),
RecursiveType: in.RecursiveType,
RecursiveOption: in.RecursiveType == recursiveTypeTrue,
Tags: in.Tags,
Option: in.Option,
})
}
return array
@ -500,11 +533,11 @@ func doMapConvertForMapOrStructValue(in doMapConvertForMapOrStructValueInput) in
// MapStrStr converts `value` to map[string]string.
// Note that there might be data copy for this map type converting.
func MapStrStr(value interface{}, tags ...string) map[string]string {
func MapStrStr(value interface{}, option ...MapOption) map[string]string {
if r, ok := value.(map[string]string); ok {
return r
}
m := Map(value, tags...)
m := Map(value, option...)
if len(m) > 0 {
vMap := make(map[string]string, len(m))
for k, v := range m {
@ -517,6 +550,7 @@ func MapStrStr(value interface{}, tags ...string) map[string]string {
// MapStrStrDeep converts `value` to map[string]string recursively.
// Note that there might be data copy for this map type converting.
// Deprecated: used MapStrStr instead.
func MapStrStrDeep(value interface{}, tags ...string) map[string]string {
if r, ok := value.(map[string]string); ok {
return r

View File

@ -9,23 +9,19 @@ package gconv
import "github.com/gogf/gf/v2/internal/json"
// SliceMap is alias of Maps.
func SliceMap(any interface{}) []map[string]interface{} {
return Maps(any)
func SliceMap(any interface{}, option ...MapOption) []map[string]interface{} {
return Maps(any, option...)
}
// SliceMapDeep is alias of MapsDeep.
// Deprecated: used SliceMap instead.
func SliceMapDeep(any interface{}) []map[string]interface{} {
return MapsDeep(any)
}
// SliceStruct is alias of Structs.
func SliceStruct(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) {
return Structs(params, pointer, mapping...)
}
// Maps converts `value` to []map[string]interface{}.
// Note that it automatically checks and converts json string to []map if `value` is string/[]byte.
func Maps(value interface{}, tags ...string) []map[string]interface{} {
func Maps(value interface{}, option ...MapOption) []map[string]interface{} {
if value == nil {
return nil
}
@ -62,7 +58,7 @@ func Maps(value interface{}, tags ...string) []map[string]interface{} {
}
list := make([]map[string]interface{}, len(array))
for k, v := range array {
list[k] = Map(v, tags...)
list[k] = Map(v, option...)
}
return list
}
@ -71,6 +67,7 @@ func Maps(value interface{}, tags ...string) []map[string]interface{} {
// MapsDeep converts `value` to []map[string]interface{} recursively.
//
// TODO completely implement the recursive converting for all types.
// Deprecated: used Maps instead.
func MapsDeep(value interface{}, tags ...string) []map[string]interface{} {
if value == nil {
return nil

View File

@ -20,6 +20,11 @@ func Structs(params interface{}, pointer interface{}, paramKeyToAttrMap ...map[s
return Scan(params, pointer, paramKeyToAttrMap...)
}
// SliceStruct is alias of Structs.
func SliceStruct(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) {
return Structs(params, pointer, mapping...)
}
// StructsTag acts as Structs but also with support for priority tag feature, which retrieves the
// specified tags for `params` key-value items to struct attribute names mapping.
// The parameter `priorityTag` supports multiple tags that can be joined with char ','.

View File

@ -946,8 +946,8 @@ func Test_Map_StructWithJsonTag_All(t *testing.T) {
ssa: "222",
}
user2 := &user1
_ = gconv.Map(user1, "Ss")
map1 := gconv.Map(user1, "json", "json2")
_ = gconv.Map(user1, gconv.MapOption{Tags: []string{"Ss"}})
map1 := gconv.Map(user1, gconv.MapOption{Tags: []string{"json", "json2"}})
map2 := gconv.Map(user2)
map3 := gconv.Map(user3)
t.Assert(map1["Uid"], 100)

View File

@ -617,6 +617,53 @@ func TestMapWithJsonOmitEmpty(t *testing.T) {
Key: "",
Value: 1,
}
t.Assert(gconv.Map(s), g.Map{"Value": 1})
m1 := gconv.Map(s)
t.Assert(m1, g.Map{
"Key": "",
"Value": 1,
})
m2 := gconv.Map(s, gconv.MapOption{
Deep: false,
OmitEmpty: true,
Tags: nil,
})
t.Assert(m2, g.Map{
"Value": 1,
})
})
gtest.C(t, func(t *gtest.T) {
type ProductConfig struct {
Pid int `v:"required" json:"pid,omitempty"`
TimeSpan int `v:"required" json:"timeSpan,omitempty"`
}
type CreateGoodsDetail struct {
ProductConfig
AutoRenewFlag int `v:"required" json:"autoRenewFlag"`
}
s := &CreateGoodsDetail{
ProductConfig: ProductConfig{
Pid: 1,
TimeSpan: 0,
},
AutoRenewFlag: 0,
}
m1 := gconv.Map(s)
t.Assert(m1, g.Map{
"pid": 1,
"timeSpan": 0,
"autoRenewFlag": 0,
})
m2 := gconv.Map(s, gconv.MapOption{
Deep: false,
OmitEmpty: true,
Tags: nil,
})
t.Assert(m2, g.Map{
"pid": 1,
"autoRenewFlag": 0,
})
})
}

View File

@ -44,7 +44,7 @@ func newValidationError(code gcode.Code, rules []fieldRule, fieldRuleErrorMap ma
for field, ruleErrorMap := range fieldRuleErrorMap {
for rule, err := range ruleErrorMap {
if !gerror.HasStack(err) {
ruleErrorMap[rule] = gerror.NewOption(gerror.Option{
ruleErrorMap[rule] = gerror.NewWithOption(gerror.Option{
Stack: false,
Text: gstr.Trim(err.Error()),
Code: code,

View File

@ -311,24 +311,28 @@ func Test_Datetime(t *testing.T) {
func Test_DateFormat(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
val1 := "2010"
val2 := "201011"
val3 := "2010.11"
val4 := "201011-01"
val5 := "2010~11~01"
val6 := "2010-11~01"
err1 := g.Validator().Data(val1).Rules("date-format:Y").Run(ctx)
err2 := g.Validator().Data(val2).Rules("date-format:Ym").Run(ctx)
err3 := g.Validator().Data(val3).Rules("date-format:Y.m").Run(ctx)
err4 := g.Validator().Data(val4).Rules("date-format:Ym-d").Run(ctx)
err5 := g.Validator().Data(val5).Rules("date-format:Y~m~d").Run(ctx)
err6 := g.Validator().Data(val6).Rules("date-format:Y~m~d").Run(ctx)
t.Assert(err1, nil)
t.Assert(err2, nil)
t.Assert(err3, nil)
t.Assert(err4, nil)
t.Assert(err5, nil)
t.AssertNE(err6, nil)
m := g.MapStrStr{
"2010": "date-format:Y",
"201011": "date-format:Ym",
"2010.11": "date-format:Y.m",
"201011-01": "date-format:Ym-d",
"2010~11~01": "date-format:Y~m~d",
"2010-11~01": "date-format:Y-m~d",
"2023-09-10T19:46:31Z": "date-format:2006-01-02\\T15:04:05Z07:00", // RFC3339
}
for k, v := range m {
err := g.Validator().Data(k).Rules(v).Run(ctx)
t.AssertNil(err)
}
})
gtest.C(t, func(t *gtest.T) {
errM := g.MapStrStr{
"2010-11~01": "date-format:Y~m~d",
}
for k, v := range errM {
err := g.Validator().Data(k).Rules(v).Run(ctx)
t.AssertNE(err, nil)
}
})
gtest.C(t, func(t *gtest.T) {
t1 := gtime.Now()

View File

@ -2,5 +2,5 @@ package gf
const (
// VERSION is the current GoFrame version.
VERSION = "v2.5.7"
VERSION = "v2.6.0"
)