change Error from struct to interface for package gvalid;error string update for package gdb

This commit is contained in:
John Guo
2021-05-18 20:51:31 +08:00
parent 0dfd968824
commit c8c28770fb
20 changed files with 175 additions and 63 deletions

View File

@ -1,6 +1,7 @@
package main
import (
"context"
"fmt"
"github.com/gogf/gf/i18n/gi18n"
@ -13,6 +14,6 @@ func main() {
if err != nil {
panic(err)
}
fmt.Println(t.Translate(`hello`))
fmt.Println(t.Translate(`{#hello}{#world}!`))
fmt.Println(t.Translate(context.TODO(), `hello`))
fmt.Println(t.Translate(context.TODO(), `{#hello}{#world}!`))
}

View File

@ -1,6 +1,7 @@
package main
import (
"context"
"fmt"
"github.com/gogf/gf/i18n/gi18n"
@ -13,6 +14,6 @@ func main() {
if err != nil {
panic(err)
}
fmt.Println(t.Translate(`hello`))
fmt.Println(t.Translate(`{#hello}{#world}!`))
fmt.Println(t.Translate(context.TODO(), `hello`))
fmt.Println(t.Translate(context.TODO(), `{#hello}{#world}!`))
}

View File

@ -1,8 +1,10 @@
package main
import (
"context"
"fmt"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/i18n/gi18n"
)
func main() {
@ -10,6 +12,12 @@ func main() {
orderId = 865271654
orderAmount = 99.8
)
fmt.Println(g.I18n().Tfl(`en`, `{#OrderPaid}`, orderId, orderAmount))
fmt.Println(g.I18n().Tfl(`zh-CN`, `{#OrderPaid}`, orderId, orderAmount))
fmt.Println(g.I18n().Tf(
gi18n.WithLanguage(context.TODO(), `en`),
`{#OrderPaid}`, orderId, orderAmount,
))
fmt.Println(g.I18n().Tf(
gi18n.WithLanguage(context.TODO(), `zh-CN`),
`{#OrderPaid}`, orderId, orderAmount,
))
}

View File

@ -2,15 +2,19 @@ package main
import (
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/i18n/gi18n"
"github.com/gogf/gf/net/ghttp"
)
func main() {
g.I18n().SetPath("/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/.example/i18n/gi18n/i18n")
s := g.Server()
s.BindHandler("/", func(r *ghttp.Request) {
r.Response.WriteTplContent(`{#hello}{#world}!`, g.Map{
"I18nLanguage": r.Get("lang", "zh-CN"),
s.Group("/", func(group *ghttp.RouterGroup) {
group.Middleware(func(r *ghttp.Request) {
r.SetCtx(gi18n.WithLanguage(r.Context(), "zh-CN"))
r.Middleware.Next()
})
group.ALL("/", func(r *ghttp.Request) {
r.Response.WriteTplContent(`{#hello}{#world}!`)
})
})
s.SetPort(8199)

View File

@ -0,0 +1,64 @@
package main
import (
"bytes"
"fmt"
"github.com/gogf/gf/container/garray"
"github.com/gogf/gf/crypto/gmd5"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/internal/json"
"github.com/gogf/gf/net/ghttp"
"github.com/gogf/gf/os/gtime"
"github.com/gogf/gf/util/gconv"
"github.com/gogf/gf/util/guid"
"github.com/gogf/gf/util/gutil"
"io/ioutil"
"net/http"
)
const (
appId = "123"
appSecret = "456"
)
// 注入统一的接口签名参数
func injectSignature(jsonContent []byte) []byte {
var m map[string]interface{}
_ = json.Unmarshal(jsonContent, &m)
if len(m) > 0 {
m["appid"] = appId
m["nonce"] = guid.S()
m["timestamp"] = gtime.Timestamp()
var (
keyArray = garray.NewSortedStrArrayFrom(gutil.Keys(m))
sigContent string
)
keyArray.Iterator(func(k int, v string) bool {
sigContent += v
sigContent += gconv.String(m[v])
return true
})
m["signature"] = gmd5.MustEncryptString(gmd5.MustEncryptString(sigContent) + appSecret)
jsonContent, _ = json.Marshal(m)
}
return jsonContent
}
func main() {
c := g.Client()
c.Use(func(c *ghttp.Client, r *http.Request) (resp *ghttp.ClientResponse, err error) {
bodyBytes, _ := ioutil.ReadAll(r.Body)
if len(bodyBytes) > 0 {
// 注入签名相关参数修改Request原有的提交参数
bodyBytes = injectSignature(bodyBytes)
r.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
r.ContentLength = int64(len(bodyBytes))
}
return c.Next(r)
})
content := c.ContentJson().PostContent("http://127.0.0.1:8199/", g.Map{
"name": "goframe",
"site": "https://goframe.org",
})
fmt.Println(content)
}

View File

@ -0,0 +1,17 @@
package main
import (
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/net/ghttp"
)
func main() {
s := g.Server()
s.Group("/", func(group *ghttp.RouterGroup) {
group.ALL("/", func(r *ghttp.Request) {
r.Response.Write(r.GetMap())
})
})
s.SetPort(8199)
s.Run()
}

View File

@ -25,7 +25,7 @@ func main() {
//fmt.Println(r.GetBody())
if err := r.Parse(&req); err != nil {
// Validation error.
if v, ok := err.(*gvalid.Error); ok {
if v, ok := err.(gvalid.Error); ok {
r.Response.WriteJsonExit(RegisterRes{
Code: 1,
Error: v.FirstString(),

View File

@ -24,7 +24,7 @@ func main() {
var req *RegisterReq
if err := r.Parse(&req); err != nil {
// Validation error.
if v, ok := err.(*gvalid.Error); ok {
if v, ok := err.(gvalid.Error); ok {
r.Response.WriteJsonExit(RegisterRes{
Code: 1,
Error: v.FirstString(),

View File

@ -339,7 +339,7 @@ func New(group ...string) (db DB, err error) {
defer configs.RUnlock()
if len(configs.config) < 1 {
return nil, gerror.New("empty database configuration")
return nil, gerror.New("database configuration is empty, please set the database configuration before using")
}
if _, ok := configs.config[groupName]; ok {
if node, err := getConfigNodeByGroup(groupName, true); err == nil {
@ -358,13 +358,19 @@ func New(group ...string) (db DB, err error) {
}
return c.db, nil
} else {
return nil, gerror.New(fmt.Sprintf(`unsupported database type "%s"`, node.Type))
return nil, gerror.Newf(
`cannot find database driver for specified database type "%s", did you misspell type name "%s" or forget importing the database driver?`,
node.Type, node.Type,
)
}
} else {
return nil, err
}
} else {
return nil, gerror.New(fmt.Sprintf(`database configuration node "%s" is not found`, groupName))
return nil, gerror.Newf(
`database configuration node "%s" is not found, did you misspell group name "%s" or miss the database configuration?`,
groupName, groupName,
)
}
}

View File

@ -54,14 +54,14 @@ func Database(name ...string) gdb.DB {
if exampleConfigFilePath, _ := Config().GetFilePath(exampleFileName); exampleConfigFilePath != "" {
panic(gerror.Wrapf(
err,
`configuration file "%s" not found, but found "%s", did you miss renaming the configuration example file?`,
`configuration file "%s" not found, but found "%s", did you miss renaming the example configuration file?`,
Config().GetFileName(),
exampleFileName,
))
} else {
panic(gerror.Wrapf(
err,
`configuration file "%s" not found, did you miss the configuration file or the file name setting?`,
`configuration file "%s" not found, did you miss the configuration file or the misspell the configuration file name?`,
Config().GetFileName(),
))
}

View File

@ -41,7 +41,6 @@ func TranslateFormat(ctx context.Context, format string, values ...interface{})
}
// Translate translates <content> with configured language and returns the translated content.
// The parameter <language> specifies custom translation language ignoring configured language.
func Translate(ctx context.Context, content string) string {
return Instance().Translate(ctx, content)
}

View File

@ -138,7 +138,6 @@ func (m *Manager) TranslateFormat(ctx context.Context, format string, values ...
}
// Translate translates <content> with configured language.
// The parameter <language> specifies custom translation language ignoring configured language.
func (m *Manager) Translate(ctx context.Context, content string) string {
m.init()
m.mu.RLock()

View File

@ -189,7 +189,7 @@ var (
// string/map/struct/*struct.
// The optional parameter `params` specifies the extra validation parameters for some rules
// like: required-*、same、different, etc.
func Check(ctx context.Context, value interface{}, rules string, messages interface{}, params ...interface{}) *Error {
func Check(ctx context.Context, value interface{}, rules string, messages interface{}, params ...interface{}) Error {
return defaultValidator.Ctx(ctx).Check(value, rules, messages, params...)
}
@ -198,7 +198,7 @@ func Check(ctx context.Context, value interface{}, rules string, messages interf
// The parameter `rules` can be type of []string/map[string]string. It supports sequence in error result
// if `rules` is type of []string.
// The optional parameter `messages` specifies the custom error messages for specified keys and rules.
func CheckMap(ctx context.Context, params interface{}, rules interface{}, messages ...CustomMsg) *Error {
func CheckMap(ctx context.Context, params interface{}, rules interface{}, messages ...CustomMsg) Error {
return defaultValidator.Ctx(ctx).CheckMap(params, rules, messages...)
}
@ -208,7 +208,7 @@ func CheckMap(ctx context.Context, params interface{}, rules interface{}, messag
// The parameter `rules` can be type of []string/map[string]string. It supports sequence in error result
// if `rules` is type of []string.
// The optional parameter `messages` specifies the custom error messages for specified keys and rules.
func CheckStruct(ctx context.Context, object interface{}, rules interface{}, messages ...CustomMsg) *Error {
func CheckStruct(ctx context.Context, object interface{}, rules interface{}, messages ...CustomMsg) Error {
return defaultValidator.Ctx(ctx).CheckStruct(object, rules, messages...)
}
@ -218,7 +218,7 @@ func CheckStruct(ctx context.Context, object interface{}, rules interface{}, mes
// The parameter `rules` can be type of []string/map[string]string. It supports sequence in error result
// if `rules` is type of []string.
// The optional parameter `messages` specifies the custom error messages for specified keys and rules.
func CheckStructWithParamMap(ctx context.Context, object interface{}, paramMap interface{}, rules interface{}, messages ...CustomMsg) *Error {
func CheckStructWithParamMap(ctx context.Context, object interface{}, paramMap interface{}, rules interface{}, messages ...CustomMsg) Error {
return defaultValidator.Ctx(ctx).CheckStructWithParamMap(object, paramMap, rules, messages...)
}

View File

@ -14,19 +14,28 @@ import (
)
// Error is the validation error for validation result.
type Error struct {
rules []string // Rules by sequence, which is used for keeping error sequence.
errors ErrorMap // Error map.
firstKey string // The first error rule key(nil in default).
firstItem map[string]string // The first error rule value(nil in default).
type Error interface {
Current() error
Error() string
FirstItem() (key string, messages map[string]string)
FirstRule() (rule string, err string)
FirstString() (err string)
Map() map[string]string
Maps() map[string]map[string]string
String() string
Strings() (errs []string)
}
// ErrorMap is the validation error map:
// map[field]map[rule]message
type ErrorMap map[string]map[string]string
// validationError is the validation error for validation result.
type validationError struct {
rules []string // Rules by sequence, which is used for keeping error sequence.
errors map[string]map[string]string // Error map:map[field]map[rule]message
firstKey string // The first error rule key(nil in default).
firstItem map[string]string // The first error rule value(nil in default).
}
// newError creates and returns a validation error.
func newError(rules []string, errors map[string]map[string]string) *Error {
func newError(rules []string, errors map[string]map[string]string) *validationError {
for field, m := range errors {
for k, v := range m {
v = strings.Replace(v, ":attribute", field, -1)
@ -36,14 +45,14 @@ func newError(rules []string, errors map[string]map[string]string) *Error {
}
errors[field] = m
}
return &Error{
return &validationError{
rules: rules,
errors: errors,
}
}
// newErrorStr creates and returns a validation error by string.
func newErrorStr(key, err string) *Error {
func newErrorStr(key, err string) *validationError {
return newError(nil, map[string]map[string]string{
"__gvalid__": {
key: err,
@ -52,7 +61,7 @@ func newErrorStr(key, err string) *Error {
}
// Map returns the first error message as map.
func (e *Error) Map() map[string]string {
func (e *validationError) Map() map[string]string {
if e == nil {
return map[string]string{}
}
@ -61,7 +70,7 @@ func (e *Error) Map() map[string]string {
}
// Maps returns all error messages as map.
func (e *Error) Maps() ErrorMap {
func (e *validationError) Maps() map[string]map[string]string {
if e == nil {
return nil
}
@ -69,7 +78,7 @@ func (e *Error) Maps() ErrorMap {
}
// FirstItem returns the field name and error messages for the first validation rule error.
func (e *Error) FirstItem() (key string, messages map[string]string) {
func (e *validationError) FirstItem() (key string, messages map[string]string) {
if e == nil {
return "", map[string]string{}
}
@ -97,7 +106,7 @@ func (e *Error) FirstItem() (key string, messages map[string]string) {
}
// FirstRule returns the first error rule and message string.
func (e *Error) FirstRule() (rule string, err string) {
func (e *validationError) FirstRule() (rule string, err string) {
if e == nil {
return "", ""
}
@ -127,7 +136,7 @@ func (e *Error) FirstRule() (rule string, err string) {
// FirstString returns the first error message as string.
// Note that the returned message might be different if it has no sequence.
func (e *Error) FirstString() (err string) {
func (e *validationError) FirstString() (err string) {
if e == nil {
return ""
}
@ -136,7 +145,7 @@ func (e *Error) FirstString() (err string) {
}
// Current is alis of FirstString, which implements interface gerror.ApiCurrent.
func (e *Error) Current() error {
func (e *validationError) Current() error {
if e == nil {
return nil
}
@ -145,7 +154,7 @@ func (e *Error) Current() error {
}
// String returns all error messages as string, multiple error messages joined using char ';'.
func (e *Error) String() string {
func (e *validationError) String() string {
if e == nil {
return ""
}
@ -153,7 +162,7 @@ func (e *Error) String() string {
}
// Error implements interface of error.Error.
func (e *Error) Error() string {
func (e *validationError) Error() string {
if e == nil {
return ""
}
@ -161,7 +170,7 @@ func (e *Error) Error() string {
}
// Strings returns all error messages as string array.
func (e *Error) Strings() (errs []string) {
func (e *validationError) Strings() (errs []string) {
if e == nil {
return []string{}
}

View File

@ -35,12 +35,12 @@ type apiTime interface {
// string/map/struct/*struct.
// The optional parameter `params` specifies the extra validation parameters for some rules
// like: required-*、same、different, etc.
func (v *Validator) Check(value interface{}, rules string, messages interface{}, paramMap ...interface{}) *Error {
func (v *Validator) Check(value interface{}, rules string, messages interface{}, paramMap ...interface{}) Error {
return v.doCheck("", value, rules, messages, paramMap...)
}
// doCheck does the really rules validation for single key-value.
func (v *Validator) doCheck(key string, value interface{}, rules string, messages interface{}, paramMap ...interface{}) *Error {
func (v *Validator) doCheck(key string, value interface{}, rules string, messages interface{}, paramMap ...interface{}) Error {
// If there's no validation rules, it does nothing and returns quickly.
if rules == "" {
return nil
@ -136,7 +136,7 @@ func (v *Validator) doCheck(key string, value interface{}, rules string, message
index++
}
if len(errorMsgArray) > 0 {
return newError([]string{rules}, ErrorMap{
return newError([]string{rules}, map[string]map[string]string{
key: errorMsgArray,
})
}

View File

@ -16,7 +16,7 @@ import (
// The parameter `rules` can be type of []string/map[string]string. It supports sequence in error result
// if `rules` is type of []string.
// The optional parameter `messages` specifies the custom error messages for specified keys and rules.
func (v *Validator) CheckMap(params interface{}, rules interface{}, messages ...CustomMsg) *Error {
func (v *Validator) CheckMap(params interface{}, rules interface{}, messages ...CustomMsg) Error {
// If there's no validation rules, it does nothing and returns quickly.
if params == nil || rules == nil {
return nil
@ -25,7 +25,7 @@ func (v *Validator) CheckMap(params interface{}, rules interface{}, messages ...
checkRules = make(map[string]string)
customMsgs = make(CustomMsg)
errorRules = make([]string, 0)
errorMaps = make(ErrorMap)
errorMaps = make(map[string]map[string]string)
)
switch v := rules.(type) {
// Sequence tag: []sequence tag

View File

@ -16,10 +16,10 @@ import (
// CheckStruct validates struct and returns the error result.
//
// The parameter `object` should be type of struct/*struct.
// The parameter `rules` can be type of []string/map[string]string. It supports sequence in error result
// The parameter `customRules` can be type of []string/map[string]string. It supports sequence in error result
// if `rules` is type of []string.
// The optional parameter `messages` specifies the custom error messages for specified keys and rules.
func (v *Validator) CheckStruct(object interface{}, customRules interface{}, customErrorMessageMap ...CustomMsg) *Error {
// The optional parameter `customErrorMessageMap` specifies the custom error messages for specified keys and rules.
func (v *Validator) CheckStruct(object interface{}, customRules interface{}, customErrorMessageMap ...CustomMsg) Error {
var message CustomMsg
if len(customErrorMessageMap) > 0 {
message = customErrorMessageMap[0]
@ -36,10 +36,11 @@ func (v *Validator) CheckStruct(object interface{}, customRules interface{}, cus
// CheckStructWithParamMap validates struct with given parameter map and returns the error result.
//
// The parameter `object` should be type of struct/*struct.
// The parameter `rules` can be type of []string/map[string]string. It supports sequence in error result
// The parameter `paramMap` should be type of map, which specifies the parameter map used in validation.
// The parameter `customRules` can be type of []string/map[string]string. It supports sequence in error result
// if `rules` is type of []string.
// The optional parameter `messages` specifies the custom error messages for specified keys and rules.
func (v *Validator) CheckStructWithParamMap(object interface{}, paramMap interface{}, customRules interface{}, customErrorMessageMap ...CustomMsg) *Error {
// The optional parameter `customErrorMessageMap` specifies the custom error messages for specified keys and rules.
func (v *Validator) CheckStructWithParamMap(object interface{}, paramMap interface{}, customRules interface{}, customErrorMessageMap ...CustomMsg) Error {
var message CustomMsg
if len(customErrorMessageMap) > 0 {
message = customErrorMessageMap[0]
@ -53,10 +54,10 @@ func (v *Validator) CheckStructWithParamMap(object interface{}, paramMap interfa
})
}
func (v *Validator) doCheckStructWithParamMap(input *doCheckStructWithParamMapInput) *Error {
func (v *Validator) doCheckStructWithParamMap(input *doCheckStructWithParamMapInput) Error {
var (
// Returning error.
errorMaps = make(ErrorMap)
errorMaps = make(map[string]map[string]string)
)
fieldMap, err := structs.FieldMap(input.Object, aliasNameTagPriority, true)
if err != nil {
@ -77,7 +78,7 @@ func (v *Validator) doCheckStructWithParamMap(input *doCheckStructWithParamMapIn
recursiveInput.Object = field.Value
if err := v.doCheckStructWithParamMap(&recursiveInput); err != nil {
// It merges the errors into single error map.
for k, m := range err.errors {
for k, m := range err.(*validationError).errors {
errorMaps[k] = m
}
}
@ -158,7 +159,8 @@ func (v *Validator) doCheckStructWithParamMap(input *doCheckStructWithParamMapIn
}
}
}
// Merge the custom validation rules with rules in struct tag.
// The custom rules has the most high priority that can overwrite the struct tag rules.
for _, field := range tagField {
fieldName := field.Name()
// sequence tag == struct tag

View File

@ -187,4 +187,6 @@ func ExampleRegisterRule_OverwriteRequired() {
// It's required
// rule deleted
// It's required
// <nil>
// <nil>
}

View File

@ -78,7 +78,7 @@ func Test_CustomRule2(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
errStr := "data map should not be empty"
t.Assert(gvalid.Check(context.TODO(), g.Map{}, rule, errStr).String(), errStr)
t.Assert(gvalid.Check(context.TODO(), g.Map{"k": "v"}, rule, errStr).String(), nil)
t.Assert(gvalid.Check(context.TODO(), g.Map{"k": "v"}, rule, errStr), nil)
})
// Error with struct validation.
gtest.C(t, func(t *gtest.T) {
@ -121,8 +121,8 @@ func Test_CustomRule_AllowEmpty(t *testing.T) {
// Check.
gtest.C(t, func(t *gtest.T) {
errStr := "error"
t.Assert(gvalid.Check(context.TODO(), "", rule, errStr).String(), "")
t.Assert(gvalid.Check(context.TODO(), "gf", rule, errStr).String(), "")
t.Assert(gvalid.Check(context.TODO(), "", rule, errStr), nil)
t.Assert(gvalid.Check(context.TODO(), "gf", rule, errStr), nil)
t.Assert(gvalid.Check(context.TODO(), "gf2", rule, errStr).String(), errStr)
})
// Error with struct validation.
@ -136,7 +136,7 @@ func Test_CustomRule_AllowEmpty(t *testing.T) {
Data: "123456",
}
err := gvalid.CheckStruct(context.TODO(), st, nil)
t.Assert(err.String(), "")
t.Assert(err, nil)
})
// No error with struct validation.
gtest.C(t, func(t *gtest.T) {

View File

@ -18,7 +18,7 @@ import (
func TestValidator_I18n(t *testing.T) {
var (
err *gvalid.Error
err gvalid.Error
i18nManager = gi18n.New(gi18n.Options{Path: gdebug.TestDataPath("i18n")})
ctxCn = gi18n.WithLanguage(context.TODO(), "cn")
validator = gvalid.New().I18n(i18nManager)