move common used tag from packages to package gtag for maintainability (#2256)

* move common used tag from packages to package gtag for maintainability

* move common used tag from packages to package gtag for maintainability

Co-authored-by: houseme <housemecn@gmail.com>
This commit is contained in:
John Guo 2022-11-07 17:51:37 +08:00 committed by GitHub
parent 033ba588c9
commit ee58255418
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 207 additions and 176 deletions

View File

@ -25,6 +25,7 @@ import (
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/util/gtag"
"github.com/gogf/gf/v2/util/gutil"
"github.com/google/uuid"
"github.com/shopspring/decimal"
@ -49,7 +50,7 @@ const (
filterTypePattern = `(?i)^UPDATE|DELETE`
replaceSchemaPattern = `@(.+?)/([\w\.\-]+)+`
needParsedSqlInCtx gctx.StrKey = "NeedParsedSql"
OrmTagForStruct = "orm"
OrmTagForStruct = gtag.ORM
driverName = "clickhouse"
)

View File

@ -13,11 +13,11 @@ import (
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/net/goai"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/util/gmeta"
"github.com/gogf/gf/v2/util/gtag"
"github.com/gogf/gf/v2/util/gutil"
)
@ -41,21 +41,21 @@ import (
// DoRequestObj(ctx, req, &res)
func (c *Client) DoRequestObj(ctx context.Context, req, res interface{}) error {
var (
method = gmeta.Get(req, goai.TagNameMethod).String()
path = gmeta.Get(req, goai.TagNamePath).String()
method = gmeta.Get(req, gtag.Method).String()
path = gmeta.Get(req, gtag.Path).String()
)
if method == "" {
return gerror.NewCodef(
gcode.CodeInvalidParameter,
`no "%s" tag found in request object: %s`,
goai.TagNameMethod, reflect.TypeOf(req).String(),
gtag.Method, reflect.TypeOf(req).String(),
)
}
if path == "" {
return gerror.NewCodef(
gcode.CodeInvalidParameter,
`no "%s" tag found in request object: %s`,
goai.TagNamePath, reflect.TypeOf(req).String(),
gtag.Path, reflect.TypeOf(req).String(),
)
}
path = c.handlePathForObjRequest(path, req)

View File

@ -12,6 +12,7 @@ import (
"reflect"
"time"
"github.com/gogf/gf/v2/util/gtag"
"github.com/gorilla/websocket"
"github.com/gogf/gf/v2/container/gmap"
@ -180,7 +181,7 @@ var (
gracefulEnabled = false
// defaultValueTags are the struct tag names for default value storing.
defaultValueTags = []string{"d", "default"}
defaultValueTags = []string{gtag.DefaultShort, gtag.Default}
)
var (

View File

@ -19,10 +19,10 @@ import (
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/internal/consts"
"github.com/gogf/gf/v2/net/goai"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gmeta"
"github.com/gogf/gf/v2/util/gtag"
)
var (
@ -96,13 +96,13 @@ func (s *Server) setHandler(ctx context.Context, in setHandlerInput) {
// Change the registered route according to meta info from its request structure.
if handler.Info.Type != nil && handler.Info.Type.NumIn() == 2 {
var objectReq = reflect.New(handler.Info.Type.In(1))
if v := gmeta.Get(objectReq, goai.TagNamePath); !v.IsEmpty() {
if v := gmeta.Get(objectReq, gtag.Path); !v.IsEmpty() {
uri = v.String()
}
if v := gmeta.Get(objectReq, goai.TagNameMethod); !v.IsEmpty() {
if v := gmeta.Get(objectReq, gtag.Method); !v.IsEmpty() {
method = v.String()
}
if v := gmeta.Get(objectReq, goai.TagNameDomain); !v.IsEmpty() {
if v := gmeta.Get(objectReq, gtag.Domain); !v.IsEmpty() {
domain = v.String()
}
}

View File

@ -19,6 +19,7 @@ import (
"github.com/gogf/gf/v2/internal/intlog"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gtag"
)
// OpenApiV3 is the structure defined from:
@ -36,18 +37,6 @@ type OpenApiV3 struct {
ExternalDocs *ExternalDocs `json:"externalDocs,omitempty"`
}
const (
HttpMethodGet = `GET`
HttpMethodPut = `PUT`
HttpMethodPost = `POST`
HttpMethodDelete = `DELETE`
HttpMethodConnect = `CONNECT`
HttpMethodHead = `HEAD`
HttpMethodOptions = `OPTIONS`
HttpMethodPatch = `PATCH`
HttpMethodTrace = `TRACE`
)
const (
TypeInteger = `integer`
TypeNumber = `number`
@ -72,15 +61,6 @@ const (
ParameterInCookie = `cookie`
)
const (
TagNamePath = `path`
TagNameMethod = `method`
TagNameMime = `mime`
TagNameConsumes = `consumes`
TagNameType = `type`
TagNameDomain = `domain`
)
const (
validationRuleKeyForRequired = `required`
validationRuleKeyForIn = `in:`
@ -90,14 +70,14 @@ var (
defaultReadContentTypes = []string{`application/json`}
defaultWriteContentTypes = []string{`application/json`}
shortTypeMapForTag = map[string]string{
"d": "Default",
"sum": "Summary",
"sm": "Summary",
"des": "Description",
"dc": "Description",
"eg": "Example",
"egs": "Examples",
"ed": "ExternalDocs",
gtag.DefaultShort: gtag.Default,
gtag.SummaryShort: gtag.Summary,
gtag.SummaryShort2: gtag.Summary,
gtag.DescriptionShort: gtag.Description,
gtag.DescriptionShort2: gtag.Description,
gtag.ExampleShort: gtag.Example,
gtag.ExamplesShort: gtag.Examples,
gtag.ExternalDocsShort: gtag.ExternalDocs,
}
)
@ -231,7 +211,7 @@ func (oai *OpenApiV3) golangTypeToSchemaName(t reflect.Type) string {
return schemaName
}
func (oai *OpenApiV3) fileMapWithShortTags(m map[string]string) map[string]string {
func (oai *OpenApiV3) fillMapWithShortTags(m map[string]string) map[string]string {
for k, v := range shortTypeMapForTag {
if m[v] == "" && m[k] != "" {
m[v] = m[k]

View File

@ -30,7 +30,7 @@ type Operation struct {
}
func (oai *OpenApiV3) tagMapToOperation(tagMap map[string]string, operation *Operation) error {
var mergedTagMap = oai.fileMapWithShortTags(tagMap)
var mergedTagMap = oai.fillMapWithShortTags(tagMap)
if err := gconv.Struct(mergedTagMap, operation); err != nil {
return gerror.Wrap(err, `mapping struct tags to Operation failed`)
}

View File

@ -32,7 +32,7 @@ type Parameter struct {
}
func (oai *OpenApiV3) tagMapToParameter(tagMap map[string]string, parameter *Parameter) error {
var mergedTagMap = oai.fileMapWithShortTags(tagMap)
var mergedTagMap = oai.fillMapWithShortTags(tagMap)
if err := gconv.Struct(mergedTagMap, parameter); err != nil {
return gerror.Wrap(err, `mapping struct tags to Parameter failed`)
}

View File

@ -8,6 +8,7 @@ package goai
import (
"fmt"
"net/http"
"github.com/gogf/gf/v2/container/gset"
"github.com/gogf/gf/v2/errors/gcode"
@ -48,7 +49,7 @@ func (oai *OpenApiV3) newParameterRefWithStructMethod(field gstructs.Field, path
} else {
// Default the parameter input to "query" if method is "GET/DELETE".
switch gstr.ToUpper(method) {
case HttpMethodGet, HttpMethodDelete:
case http.MethodGet, http.MethodDelete:
parameter.In = ParameterInQuery
default:

View File

@ -7,6 +7,7 @@
package goai
import (
"net/http"
"reflect"
"github.com/gogf/gf/v2/container/garray"
@ -17,6 +18,7 @@ import (
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/util/gmeta"
"github.com/gogf/gf/v2/util/gtag"
)
type Path struct {
@ -97,7 +99,7 @@ func (oai *OpenApiV3) addPath(in addPathInput) error {
)
// Path check.
if in.Path == "" {
in.Path = gmeta.Get(inputObject.Interface(), TagNamePath).String()
in.Path = gmeta.Get(inputObject.Interface(), gtag.Path).String()
if in.Prefix != "" {
in.Path = gstr.TrimRight(in.Prefix, "/") + "/" + gstr.TrimLeft(in.Path, "/")
}
@ -106,7 +108,7 @@ func (oai *OpenApiV3) addPath(in addPathInput) error {
return gerror.NewCodef(
gcode.CodeMissingParameter,
`missing necessary path parameter "%s" for input struct "%s", missing tag in attribute Meta?`,
TagNamePath, inputStructTypeName,
gtag.Path, inputStructTypeName,
)
}
@ -116,13 +118,13 @@ func (oai *OpenApiV3) addPath(in addPathInput) error {
// Method check.
if in.Method == "" {
in.Method = gmeta.Get(inputObject.Interface(), TagNameMethod).String()
in.Method = gmeta.Get(inputObject.Interface(), gtag.Method).String()
}
if in.Method == "" {
return gerror.NewCodef(
gcode.CodeMissingParameter,
`missing necessary method parameter "%s" for input struct "%s", missing tag in attribute Meta?`,
TagNameMethod, inputStructTypeName,
gtag.Method, inputStructTypeName,
)
}
@ -138,8 +140,8 @@ func (oai *OpenApiV3) addPath(in addPathInput) error {
return err
}
// Allowed request mime.
if mime = inputMetaMap[TagNameMime]; mime == "" {
mime = inputMetaMap[TagNameConsumes]
if mime = inputMetaMap[gtag.Mime]; mime == "" {
mime = inputMetaMap[gtag.Consumes]
}
}
@ -179,7 +181,7 @@ func (oai *OpenApiV3) addPath(in addPathInput) error {
// Supported mime types of request.
var (
contentTypes = oai.Config.ReadContentTypes
tagMimeValue = gmeta.Get(inputObject.Interface(), TagNameMime).String()
tagMimeValue = gmeta.Get(inputObject.Interface(), gtag.Mime).String()
)
if tagMimeValue != "" {
contentTypes = gstr.SplitAndTrim(tagMimeValue, ",")
@ -224,7 +226,7 @@ func (oai *OpenApiV3) addPath(in addPathInput) error {
// Supported mime types of response.
var (
contentTypes = oai.Config.ReadContentTypes
tagMimeValue = gmeta.Get(outputObject.Interface(), TagNameMime).String()
tagMimeValue = gmeta.Get(outputObject.Interface(), gtag.Mime).String()
refInput = getResponseSchemaRefInput{
BusinessStructName: outputStructTypeName,
CommonResponseObject: oai.Config.CommonResponse,
@ -256,35 +258,35 @@ func (oai *OpenApiV3) addPath(in addPathInput) error {
// Assign to certain operation attribute.
switch gstr.ToUpper(in.Method) {
case HttpMethodGet:
case http.MethodGet:
// GET operations cannot have a requestBody.
operation.RequestBody = nil
path.Get = &operation
case HttpMethodPut:
case http.MethodPut:
path.Put = &operation
case HttpMethodPost:
case http.MethodPost:
path.Post = &operation
case HttpMethodDelete:
case http.MethodDelete:
// DELETE operations cannot have a requestBody.
operation.RequestBody = nil
path.Delete = &operation
case HttpMethodConnect:
case http.MethodConnect:
// Nothing to do for Connect.
case HttpMethodHead:
case http.MethodHead:
path.Head = &operation
case HttpMethodOptions:
case http.MethodOptions:
path.Options = &operation
case HttpMethodPatch:
case http.MethodPatch:
path.Patch = &operation
case HttpMethodTrace:
case http.MethodTrace:
path.Trace = &operation
default:
@ -354,7 +356,7 @@ func (oai *OpenApiV3) doesStructHasNoFields(s interface{}) bool {
}
func (oai *OpenApiV3) tagMapToPath(tagMap map[string]string, path *Path) error {
var mergedTagMap = oai.fileMapWithShortTags(tagMap)
var mergedTagMap = oai.fillMapWithShortTags(tagMap)
if err := gconv.Struct(mergedTagMap, path); err != nil {
return gerror.Wrap(err, `mapping struct tags to Path failed`)
}

View File

@ -22,7 +22,7 @@ type Response struct {
}
func (oai *OpenApiV3) tagMapToResponse(tagMap map[string]string, response *Response) error {
var mergedTagMap = oai.fileMapWithShortTags(tagMap)
var mergedTagMap = oai.fillMapWithShortTags(tagMap)
if err := gconv.Struct(mergedTagMap, response); err != nil {
return gerror.Wrap(err, `mapping struct tags to Response failed`)
}

View File

@ -211,7 +211,7 @@ func (oai *OpenApiV3) structToSchema(object interface{}) (*Schema, error) {
}
func (oai *OpenApiV3) tagMapToSchema(tagMap map[string]string, schema *Schema) error {
var mergedTagMap = oai.fileMapWithShortTags(tagMap)
var mergedTagMap = oai.fillMapWithShortTags(tagMap)
if err := gconv.Struct(mergedTagMap, schema); err != nil {
return gerror.Wrap(err, `mapping struct tags to Schema failed`)
}

View File

@ -9,6 +9,7 @@ package goai_test
import (
"context"
"fmt"
"net/http"
"testing"
"github.com/gogf/gf/v2/frame/g"
@ -96,14 +97,14 @@ func TestOpenApiV3_Add(t *testing.T) {
)
err = oai.Add(goai.AddInput{
Path: "/test1/{appId}",
Method: goai.HttpMethodPut,
Method: http.MethodPut,
Object: f,
})
t.AssertNil(err)
err = oai.Add(goai.AddInput{
Path: "/test1/{appId}",
Method: goai.HttpMethodPost,
Method: http.MethodPost,
Object: f,
})
t.AssertNil(err)
@ -216,7 +217,7 @@ func TestOpenApiV3_Add_AutoDetectIn(t *testing.T) {
)
err = oai.Add(goai.AddInput{
Path: path,
Method: goai.HttpMethodGet,
Method: http.MethodGet,
Object: f,
})
t.AssertNil(err)
@ -654,27 +655,27 @@ func TestOpenApiV3_CommonResponse_SubDataField(t *testing.T) {
func TestOpenApiV3_ShortTags(t *testing.T) {
type CommonReq struct {
AppId int64 `json:"appId" v:"required" in:"path" des:"应用Id" sum:"应用Id Summary"`
ResourceId string `json:"resourceId" in:"query" des:"资源Id" sum:"资源Id Summary"`
AppId int64 `json:"appId" v:"required" in:"path" dc:"应用Id" sm:"应用Id Summary"`
ResourceId string `json:"resourceId" in:"query" dc:"资源Id" sm:"资源Id Summary"`
}
type SetSpecInfo struct {
StorageType string `v:"required|in:CLOUD_PREMIUM,CLOUD_SSD,CLOUD_HSSD" des:"StorageType"`
Shards int32 `des:"shards 分片数" sum:"Shards Summary"`
Params []string `des:"默认参数(json 串-ClickHouseParams)" sum:"Params Summary"`
StorageType string `v:"required|in:CLOUD_PREMIUM,CLOUD_SSD,CLOUD_HSSD" dc:"StorageType"`
Shards int32 `dc:"shards 分片数" sm:"Shards Summary"`
Params []string `dc:"默认参数(json 串-ClickHouseParams)" sm:"Params Summary"`
}
type CreateResourceReq struct {
CommonReq
gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default" sum:"CreateResourceReq sum"`
Name string `des:"实例名称"`
Product string `des:"业务类型"`
Region string `v:"required" des:"区域"`
SetMap map[string]*SetSpecInfo `v:"required" des:"配置Map"`
SetSlice []SetSpecInfo `v:"required" des:"配置Slice"`
gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default" sm:"CreateResourceReq sum"`
Name string `dc:"实例名称"`
Product string `dc:"业务类型"`
Region string `v:"required" dc:"区域"`
SetMap map[string]*SetSpecInfo `v:"required" dc:"配置Map"`
SetSlice []SetSpecInfo `v:"required" dc:"配置Slice"`
}
type CreateResourceRes struct {
gmeta.Meta `des:"Demo Response Struct"`
FlowId int64 `des:"创建实例流程id"`
gmeta.Meta `dc:"Demo Response Struct"`
FlowId int64 `dc:"创建实例流程id"`
}
f := func(ctx context.Context, req *CreateResourceReq) (res *CreateResourceRes, err error) {
@ -688,14 +689,14 @@ func TestOpenApiV3_ShortTags(t *testing.T) {
)
err = oai.Add(goai.AddInput{
Path: "/test1/{appId}",
Method: goai.HttpMethodPut,
Method: http.MethodPut,
Object: f,
})
t.AssertNil(err)
err = oai.Add(goai.AddInput{
Path: "/test1/{appId}",
Method: goai.HttpMethodPost,
Method: http.MethodPost,
Object: f,
})
t.AssertNil(err)
@ -728,7 +729,7 @@ func TestOpenApiV3_HtmlResponse(t *testing.T) {
)
err = oai.Add(goai.AddInput{
Path: "/test",
Method: goai.HttpMethodGet,
Method: http.MethodGet,
Object: f,
})
t.AssertNil(err)
@ -775,7 +776,7 @@ func TestOpenApiV3_HtmlResponseWithCommonResponse(t *testing.T) {
err = oai.Add(goai.AddInput{
Path: "/test",
Method: goai.HttpMethodGet,
Method: http.MethodGet,
Object: f,
})
t.AssertNil(err)

View File

@ -23,18 +23,11 @@ import (
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/util/gmeta"
"github.com/gogf/gf/v2/util/gtag"
"github.com/gogf/gf/v2/util/gutil"
"github.com/gogf/gf/v2/util/gvalid"
)
const (
tagNameDc = `dc` // description.
tagNameAd = `ad` // additional
tagNameEg = `eg` // examples.
tagNameArg = `arg`
tagNameRoot = `root`
)
var (
// defaultValueTags is the struct tag names for default value storing.
defaultValueTags = []string{"d", "default"}
@ -68,7 +61,7 @@ func NewFromObject(object interface{}) (rootCmd *Command, err error) {
// Sub command creating.
var (
nameSet = gset.NewStrSet()
rootCommandName = gmeta.Get(object, tagNameRoot).String()
rootCommandName = gmeta.Get(object, gtag.Root).String()
subCommands []*Command
)
if rootCommandName == "" {
@ -155,14 +148,22 @@ func newCommandFromObjectMeta(object interface{}, name string) (command *Command
}
command.Name = name
}
if command.Brief == "" {
for _, tag := range []string{gtag.Summary, gtag.SummaryShort, gtag.SummaryShort2} {
command.Brief = metaData[tag]
if command.Brief != "" {
break
}
}
}
if command.Description == "" {
command.Description = metaData[tagNameDc]
command.Description = metaData[gtag.DescriptionShort]
}
if command.Examples == "" {
command.Examples = metaData[tagNameEg]
command.Examples = metaData[gtag.ExampleShort]
}
if command.Additional == "" {
command.Additional = metaData[tagNameAd]
command.Additional = metaData[gtag.AdditionalShort]
}
return
}
@ -354,7 +355,7 @@ func newArgumentsFromInput(object interface{}) (args []Argument, err error) {
arg.Short, reflect.TypeOf(object).String(), field.Name(),
)
}
if v, ok := metaData[tagNameArg]; ok {
if v, ok := metaData[gtag.Arg]; ok {
arg.IsArg = gconv.Bool(v)
}
if nameSet.Contains(arg.Name) {

View File

@ -10,60 +10,35 @@
// which means you cannot call them in runtime but in boot procedure.
package gtag
import (
"regexp"
"github.com/gogf/gf/v2/errors/gerror"
const (
Default = "default" // Default value tag of struct field for receiving parameters from HTTP request.
DefaultShort = "d" // Short name of Default.
Param = "param" // Parameter name for converting certain parameter to specified struct field.
ParamShort = "p" // Short name of Param.
Valid = "valid" // Validation rule tag for struct of field.
ValidShort = "v" // Short name of Valid.
NoValidation = "nv" // No validation for specified struct/field.
ORM = "orm" // ORM tag for ORM feature, which performs different features according scenarios.
Arg = "arg" // Arg tag for struct, usually for command argument option.
Brief = "brief" // Brief tag for struct, usually be considered as summary.
Root = "root" // Root tag for struct, usually for nested commands management.
Additional = "additional" // Additional tag for struct, usually for additional description of command.
AdditionalShort = "ad" // Short name of Additional.
Path = `path` // Route path for HTTP request.
Method = `method` // Route method for HTTP request.
Domain = `domain` // Route domain for HTTP request.
Mime = `mime` // MIME type for HTTP request/response.
Consumes = `consumes` // MIME type for HTTP request.
Summary = `summary` // Summary for struct, usually for OpenAPI in request struct.
SummaryShort = `sm` // Short name of Summary.
SummaryShort2 = `sum` // Short name of Summary.
Description = `description` // Description for struct, usually for OpenAPI in request struct.
DescriptionShort = `dc` // Short name of Description.
DescriptionShort2 = `des` // Short name of Description.
Example = `example` // Example for struct, usually for OpenAPI in request struct.
ExampleShort = `eg` // Short name of Example.
Examples = `examples` // Examples for struct, usually for OpenAPI in request struct.
ExamplesShort = `egs` // Short name of Examples.
ExternalDocs = `externalDocs` // External docs for struct, always for OpenAPI in request struct.
ExternalDocsShort = `ed` // Short name of ExternalDocs.
)
var (
data = make(map[string]string)
regex = regexp.MustCompile(`\{(.+?)\}`)
)
// Set sets tag content for specified name.
// Note that it panics if `name` already exists.
func Set(name, value string) {
if _, ok := data[name]; ok {
panic(gerror.Newf(`value for tag name "%s" already exists`, name))
}
data[name] = value
}
// SetOver performs as Set, but it overwrites the old value if `name` already exists.
func SetOver(name, value string) {
data[name] = value
}
// Sets sets multiple tag content by map.
func Sets(m map[string]string) {
for k, v := range m {
Set(k, v)
}
}
// SetsOver performs as Sets, but it overwrites the old value if `name` already exists.
func SetsOver(m map[string]string) {
for k, v := range m {
SetOver(k, v)
}
}
// Get retrieves and returns the stored tag content for specified name.
func Get(name string) string {
return data[name]
}
// Parse parses and returns the content by replacing all tag name variable to
// its content for given `content`.
// Eg:
// gtag.Set("demo", "content")
// Parse(`This is {demo}`) -> `This is content`.
func Parse(content string) string {
return regex.ReplaceAllStringFunc(content, func(s string) string {
if v, ok := data[s[1:len(s)-1]]; ok {
return v
}
return s
})
}

65
util/gtag/gtag_func.go Normal file
View File

@ -0,0 +1,65 @@
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package gtag
import (
"regexp"
"github.com/gogf/gf/v2/errors/gerror"
)
var (
data = make(map[string]string)
regex = regexp.MustCompile(`\{(.+?)\}`)
)
// Set sets tag content for specified name.
// Note that it panics if `name` already exists.
func Set(name, value string) {
if _, ok := data[name]; ok {
panic(gerror.Newf(`value for tag name "%s" already exists`, name))
}
data[name] = value
}
// SetOver performs as Set, but it overwrites the old value if `name` already exists.
func SetOver(name, value string) {
data[name] = value
}
// Sets sets multiple tag content by map.
func Sets(m map[string]string) {
for k, v := range m {
Set(k, v)
}
}
// SetsOver performs as Sets, but it overwrites the old value if `name` already exists.
func SetsOver(m map[string]string) {
for k, v := range m {
SetOver(k, v)
}
}
// Get retrieves and returns the stored tag content for specified name.
func Get(name string) string {
return data[name]
}
// Parse parses and returns the content by replacing all tag name variable to
// its content for given `content`.
// Eg:
// gtag.Set("demo", "content")
// Parse(`This is {demo}`) -> `This is content`.
func Parse(content string) string {
return regex.ReplaceAllStringFunc(content, func(s string) string {
if v, ok := data[s[1:len(s)-1]]; ok {
return v
}
return s
})
}

View File

@ -15,6 +15,7 @@ import (
"github.com/gogf/gf/v2/internal/intlog"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/util/gtag"
)
// CustomMsg is the custom error message type,
@ -42,7 +43,7 @@ const (
internalErrorMapKey = "__InternalError__" // error map key for internal errors.
internalDefaultRuleName = "__default__" // default rule name for i18n error message format if no i18n message found for specified error rule.
ruleMessagePrefixForI18n = "gf.gvalid.rule." // prefix string for each rule configuration in i18n content.
noValidationTagName = "nv" // no validation tag name for struct attribute.
noValidationTagName = gtag.NoValidation // no validation tag name for struct attribute.
ruleNameRegex = "regex" // the name for rule "regex"
ruleNameNotRegex = "not-regex" // the name for rule "not-regex"
ruleNameForeach = "foreach" // the name for rule "foreach"
@ -60,8 +61,11 @@ var (
internalDefaultRuleName: "The {field} value `{value}` is invalid",
}
structTagPriority = []string{"gvalid", "valid", "v"} // structTagPriority specifies the validation tag priority array.
aliasNameTagPriority = []string{"param", "params", "p"} // aliasNameTagPriority specifies the alias tag priority array.
// structTagPriority specifies the validation tag priority array.
structTagPriority = []string{gtag.Valid, gtag.ValidShort}
// aliasNameTagPriority specifies the alias tag priority array.
aliasNameTagPriority = []string{gtag.Param, gtag.ParamShort}
// all internal error keys.
internalErrKeyMap = map[string]string{

View File

@ -116,8 +116,8 @@ func Test_CheckStruct(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type LoginRequest struct {
Username string `json:"username" gvalid:"username@required#用户名不能为空"`
Password string `json:"password" gvalid:"password@required#登录密码不能为空"`
Username string `json:"username" valid:"username@required#用户名不能为空"`
Password string `json:"password" valid:"password@required#登录密码不能为空"`
}
var login LoginRequest
err := g.Validator().Data(login).Run(context.TODO())
@ -129,8 +129,8 @@ func Test_CheckStruct(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type LoginRequest struct {
Username string `json:"username" gvalid:"@required#用户名不能为空"`
Password string `json:"password" gvalid:"@required#登录密码不能为空"`
Username string `json:"username" valid:"@required#用户名不能为空"`
Password string `json:"password" valid:"@required#登录密码不能为空"`
}
var login LoginRequest
err := g.Validator().Data(login).Run(context.TODO())
@ -139,8 +139,8 @@ func Test_CheckStruct(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type LoginRequest struct {
username string `json:"username" gvalid:"username@required#用户名不能为空"`
Password string `json:"password" gvalid:"password@required#登录密码不能为空"`
username string `json:"username" valid:"username@required#用户名不能为空"`
Password string `json:"password" valid:"password@required#登录密码不能为空"`
}
var login LoginRequest
err := g.Validator().Data(login).Run(context.TODO())
@ -151,10 +151,10 @@ func Test_CheckStruct(t *testing.T) {
// gvalid tag
gtest.C(t, func(t *gtest.T) {
type User struct {
Id int `gvalid:"uid@required|min:10#|ID不能为空"`
Age int `gvalid:"age@required#年龄不能为空"`
Username string `json:"username" gvalid:"username@required#用户名不能为空"`
Password string `json:"password" gvalid:"password@required#登录密码不能为空"`
Id int `valid:"uid@required|min:10#|ID不能为空"`
Age int `valid:"age@required#年龄不能为空"`
Username string `json:"username" valid:"username@required#用户名不能为空"`
Password string `json:"password" valid:"password@required#登录密码不能为空"`
}
user := &User{
Id: 1,
@ -169,10 +169,10 @@ func Test_CheckStruct(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type User struct {
Id int `gvalid:"uid@required|min:10#|ID不能为空"`
Age int `gvalid:"age@required#年龄不能为空"`
Username string `json:"username" gvalid:"username@required#用户名不能为空"`
Password string `json:"password" gvalid:"password@required#登录密码不能为空"`
Id int `valid:"uid@required|min:10#|ID不能为空"`
Age int `valid:"age@required#年龄不能为空"`
Username string `json:"username" valid:"username@required#用户名不能为空"`
Password string `json:"password" valid:"password@required#登录密码不能为空"`
}
user := &User{
Id: 1,
@ -192,10 +192,10 @@ func Test_CheckStruct(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type User struct {
Id int `gvalid:"uid@required|min:10#ID不能为空"`
Age int `gvalid:"age@required#年龄不能为空"`
Username string `json:"username" gvalid:"username@required#用户名不能为空"`
Password string `json:"password" gvalid:"password@required#登录密码不能为空"`
Id int `valid:"uid@required|min:10#ID不能为空"`
Age int `valid:"age@required#年龄不能为空"`
Username string `json:"username" valid:"username@required#用户名不能为空"`
Password string `json:"password" valid:"password@required#登录密码不能为空"`
}
user := &User{
Id: 1,
@ -212,8 +212,8 @@ func Test_CheckStruct(t *testing.T) {
type User struct {
Id int `valid:"uid@required|min:10#|ID不能为空"`
Age int `valid:"age@required#年龄不能为空"`
Username string `json:"username" gvalid:"username@required#用户名不能为空"`
Password string `json:"password" gvalid:"password@required#登录密码不能为空"`
Username string `json:"username" valid:"username@required#用户名不能为空"`
Password string `json:"password" valid:"password@required#登录密码不能为空"`
}
user := &User{
Id: 1,