diff --git a/README.md b/README.md index 3c28a53..5861455 100644 --- a/README.md +++ b/README.md @@ -39,3 +39,35 @@ func main() { _ = custom } ``` + +### Log 快速使用 + +```go +package main + +import ( + "github.com/inis-io/aide/dto" + "github.com/inis-io/aide/facade" +) + +func main() { + // 1) 初始化全局日志(推荐在应用启动时执行一次) + facade.LogInst.Init(dto.LogConfig{ + Enable: true, + Size: 10, // 单个日志文件大小(MB) + Age: 15, // 日志保留天数 + Backups: 30, // 最大备份数量 + }) + + // 2) 使用全局实例(两种方式都支持) + facade.Log.Info(map[string]any{"module": "user", "id": 1001}, "create user") + facade.Warn(map[string]any{"module": "user", "id": 1001}, "slow query") + + // 3) 按配置创建独立实例(适合临时调试、多租户) + custom := facade.Log.NewLog(dto.LogConfig{Enable: true, Size: 5, Age: 3, Backups: 5}) + custom.Debug(map[string]any{"traceId": "T-10086"}, "debug once") +} +``` + +> `dto.LogConfig` 默认值:`Enable=true`、`Size=2`、`Age=7`、`Backups=20`。 + diff --git a/dto/log.go b/dto/log.go new file mode 100644 index 0000000..b220117 --- /dev/null +++ b/dto/log.go @@ -0,0 +1,15 @@ +package dto + +// LogConfig - 日志配置 +type LogConfig struct { + // Enable - 是否启用日志 + Enable bool `json:"enable" default:"true"` + // Size - 单个日志文件大小(MB) + Size int `json:"size" default:"2"` + // Age - 日志文件保存天数 + Age int `json:"age" default:"7"` + // Backups - 日志文件最大保存数量 + Backups int `json:"backups" default:"20"` + // Hash - 计算配置是否发生变更 + Hash string `json:"hash"` +} \ No newline at end of file diff --git a/facade/log.go b/facade/log.go new file mode 100644 index 0000000..a01ff36 --- /dev/null +++ b/facade/log.go @@ -0,0 +1,343 @@ +package facade + +import ( + "fmt" + "sort" + "strings" + "time" + + "github.com/inis-io/aide/dto" + "github.com/inis-io/aide/utils" + "github.com/spf13/cast" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" + "gopkg.in/natefinch/lumberjack.v2" +) + +// LogInst - 日志配置控制器实例 +var LogInst = &LogClass{} + +// LogClass - 日志配置控制器 +type LogClass struct { + // 记录配置 Hash 值,用于检测配置文件是否有变化 + Hash string `json:"hash"` + // 当前日志配置(由调用方注入) + Config dto.LogConfig `json:"config"` + // 是否已经注入过配置 + HasConfig bool `json:"hasConfig"` + // 日志级别 + Level string `json:"level"` + // 日志内容 + Msg string `json:"msg"` +} + +func init() { LogInst.Init() } + +// normConfig - 统一配置默认值,避免不同项目接入时行为不一致 +func (this *LogClass) normConfig(config dto.LogConfig) dto.LogConfig { + + if config.Size <= 0 { + config.Size = 2 + } + if config.Age <= 0 { + config.Age = 7 + } + if config.Backups <= 0 { + config.Backups = 20 + } + + // 仅当是空配置时启用默认值,避免覆盖调用方显式关闭日志。 + if !config.Enable && config.Hash == "" && config.Size == 2 && config.Age == 7 && config.Backups == 20 { + config.Enable = true + } + + if utils.Is.Empty(config.Hash) { + config.Hash = utils.Hash.Sum32(utils.Json.Encode(config)) + } + + return config +} + +// defaultConfig - 获取默认日志配置 +func (this *LogClass) defaultConfig() dto.LogConfig { + return LogInst.normConfig(dto.LogConfig{Enable: true}) +} + +// useDefaultLog - 使用默认配置激活日志 +func (this *LogClass) useDefaultLog() { + conf := LogInst.defaultConfig() + this.Config = conf + this.Hash = conf.Hash + this.HasConfig = false + LogInst.setActiveLog(conf) +} + +// setConfig - 注入日志配置 +func (this *LogClass) setConfig(config dto.LogConfig) *LogClass { + this.Config = LogInst.normConfig(config) + this.HasConfig = true + return this +} + +// ReloadIfChanged - 当配置发生变化时重新加载日志 +func (this *LogClass) ReloadIfChanged(config ...dto.LogConfig) { + if len(config) > 0 { + this.setConfig(config[0]) + } + if !this.HasConfig { + return + } + + // hash 变化,说明配置有更新 + if this.Hash != this.Config.Hash { + this.Init() + } +} + +// Init - 初始化日志 +func (this *LogClass) Init(config ...dto.LogConfig) { + + if len(config) > 0 { + this.setConfig(config[0]) + } + + if !this.HasConfig { + LogInst.useDefaultLog() + return + } + + this.Config = LogInst.normConfig(this.Config) + this.Hash = this.Config.Hash + LogInst.setActiveLog(this.Config) +} + +// setActiveLog - 按配置切换当前活动日志实现 +func (this *LogClass) setActiveLog(config dto.LogConfig) { + conf := LogInst.normConfig(config) + this.Config = conf + + LogInfo = this.NewLevel("info", conf) + LogWarn = this.NewLevel("warn", conf) + LogError = this.NewLevel("error", conf) + LogDebug = this.NewLevel("debug", conf) + + Log = &log{ + Config: conf, + InfoLogger: LogInfo, + WarnLogger: LogWarn, + ErrorLogger: LogError, + DebugLogger: LogDebug, + } +} + +// newWithConfig - 使用传入配置创建新的日志实例 +func (this *LogClass) newWithConfig(config dto.LogConfig) LogAPI { + conf := LogInst.normConfig(config) + return &log{ + Config: conf, + InfoLogger: this.NewLevel("info", conf), + WarnLogger: this.NewLevel("warn", conf), + ErrorLogger: this.NewLevel("error", conf), + DebugLogger: this.NewLevel("debug", conf), + } +} + +// ensureLog - 保证默认日志实例可用 +func (this *LogClass) ensureLog() { + if Log == nil { + LogInst.useDefaultLog() + } +} + +// Write - 写入日志 +func (this *LogClass) Write(data map[string]any, msg ...any) { + this.ensureLog() + + level := strings.ToLower(strings.TrimSpace(this.Level)) + if len(msg) == 0 { + msg = append(msg, level) + } + if level == "" { + level = "info" + } + + this.Msg = cast.ToString(msg[0]) + + switch level { + case "warn": + Log.Warn(data, this.Msg) + case "error": + Log.Error(data, this.Msg) + case "debug": + Log.Debug(data, this.Msg) + default: + Log.Info(data, this.Msg) + } +} + +// NewLevel - 创建日志通道 +func (this *LogClass) NewLevel(levelName string, config ...dto.LogConfig) *zap.Logger { + + conf := this.Config + if len(config) > 0 { + conf = LogInst.normConfig(config[0]) + } else { + conf = LogInst.normConfig(conf) + } + + path := fmt.Sprintf("runtime/logs/%s/%s.log", time.Now().Format("2006-01-02"), levelName) + + write := zapcore.AddSync(&lumberjack.Logger{ + Filename: path, + MaxAge: conf.Age, + MaxSize: conf.Size, + MaxBackups: conf.Backups, + }) + + encoder := func() zapcore.Encoder { + + encoderConfig := zap.NewProductionEncoderConfig() + encoderConfig.TimeKey = "time" + encoderConfig.EncodeTime = zapcore.TimeEncoderOfLayout("2006-01-02 15:04:05") + encoderConfig.EncodeCaller = zapcore.ShortCallerEncoder + + return zapcore.NewJSONEncoder(encoderConfig) + } + + level := new(zapcore.Level) + if err := level.UnmarshalText([]byte(levelName)); err != nil { + _ = level.UnmarshalText([]byte("info")) + } + core := zapcore.NewCore(encoder(), write, level) + + return zap.New(core) +} + +// LogInfo - info日志通道 +var LogInfo *zap.Logger + +// LogWarn - warn日志通道 +var LogWarn *zap.Logger + +// LogError - error日志通道 +var LogError *zap.Logger + +// LogDebug - debug日志通道 +var LogDebug *zap.Logger + +// LogAPI - 统一日志能力接口 +type LogAPI interface { + Info(data map[string]any, msg ...any) + Warn(data map[string]any, msg ...any) + Error(data map[string]any, msg ...any) + Debug(data map[string]any, msg ...any) + NewLog(config dto.LogConfig) LogAPI +} + +// log - 日志结构体 +type log struct { + Config dto.LogConfig + InfoLogger *zap.Logger + WarnLogger *zap.Logger + ErrorLogger *zap.Logger + DebugLogger *zap.Logger +} + +// Log - 日志 +var Log LogAPI + +// NewLog - 使用自定义配置创建新的日志实例 +func (this *log) NewLog(config dto.LogConfig) LogAPI { + return LogInst.newWithConfig(config) +} + +func (this *log) Info(data map[string]any, msg ...any) { + this.write(this.InfoLogger, "info", data, msg...) +} + +func (this *log) Warn(data map[string]any, msg ...any) { + this.write(this.WarnLogger, "warn", data, msg...) +} + +func (this *log) Error(data map[string]any, msg ...any) { + this.write(this.ErrorLogger, "error", data, msg...) +} + +func (this *log) Debug(data map[string]any, msg ...any) { + this.write(this.DebugLogger, "debug", data, msg...) +} + +// write - 统一日志写入实现 +func (this *log) write(logger *zap.Logger, level string, data map[string]any, msg ...any) { + if !this.Config.Enable { + return + } + + if len(msg) == 0 { + msg = append(msg, level) + } + + content := cast.ToString(msg[0]) + if strings.TrimSpace(content) == "" { + content = level + } + + fields := this.mapFields(data) + logger = this.ensureLogger(logger) + + switch level { + case "warn": + logger.Warn(content, fields...) + case "error": + logger.Error(content, fields...) + case "debug": + logger.Debug(content, fields...) + default: + logger.Info(content, fields...) + } +} + +func (this *log) mapFields(data map[string]any) []zap.Field { + if len(data) == 0 { + return nil + } + + keys := make([]string, 0, len(data)) + for key := range data { + keys = append(keys, key) + } + sort.Strings(keys) + + fields := make([]zap.Field, 0, len(keys)) + for _, key := range keys { + fields = append(fields, zap.Any(key, data[key])) + } + return fields +} + +func (this *log) ensureLogger(logger *zap.Logger) *zap.Logger { + if logger == nil { + return zap.NewNop() + } + return logger +} + +// func Info(data map[string]any, msg ...any) { +// LogInst.ensureLog() +// Log.Info(data, msg...) +// } +// +// func Warn(data map[string]any, msg ...any) { +// LogInst.ensureLog() +// Log.Warn(data, msg...) +// } +// +// func Error(data map[string]any, msg ...any) { +// LogInst.ensureLog() +// Log.Error(data, msg...) +// } +// +// func Debug(data map[string]any, msg ...any) { +// LogInst.ensureLog() +// Log.Debug(data, msg...) +// } diff --git a/facade/storage.go b/facade/storage.go index fd2534f..0abea14 100644 --- a/facade/storage.go +++ b/facade/storage.go @@ -28,7 +28,7 @@ type StorageClass struct { // 是否已经注入过配置 HasConfig bool `json:"hasConfig"` // 读写锁,保护配置和Hash的并发访问 - mu sync.RWMutex + Mutex sync.RWMutex } func init() { StorageInst.Init() } @@ -78,11 +78,11 @@ func (this *StorageClass) defaultConfig() dto.StorageConfig { func (this *StorageClass) useDefaultStorage() { conf := StorageInst.defaultConfig() - this.mu.Lock() + this.Mutex.Lock() this.Config = conf this.Hash = conf.Hash this.HasConfig = false - this.mu.Unlock() + this.Mutex.Unlock() StorageInst.setActiveStorage(conf) } @@ -92,9 +92,9 @@ func (this *StorageClass) setActiveStorage(config dto.StorageConfig) { conf := StorageInst.normConfig(config) - this.mu.Lock() + this.Mutex.Lock() this.Config = conf - this.mu.Unlock() + this.Mutex.Unlock() Storage = StorageInst.newWithConfig(conf) @@ -136,8 +136,8 @@ func (this *StorageClass) newWithConfig(config dto.StorageConfig) StorageAPI { // setConfig - 注入存储配置 func (this *StorageClass) setConfig(config dto.StorageConfig) *StorageClass { - this.mu.Lock() - defer this.mu.Unlock() + this.Mutex.Lock() + defer this.Mutex.Unlock() this.Config = StorageInst.normConfig(config) this.HasConfig = true @@ -151,11 +151,11 @@ func (this *StorageClass) ReloadIfChanged(config ...dto.StorageConfig) { this.setConfig(config[0]) } - this.mu.RLock() + this.Mutex.RLock() hasConfig := this.HasConfig hash := this.Hash confHash := this.Config.Hash - this.mu.RUnlock() + this.Mutex.RUnlock() if !hasConfig { return @@ -174,10 +174,10 @@ func (this *StorageClass) Init(config ...dto.StorageConfig) { this.setConfig(config[0]) } - this.mu.RLock() + this.Mutex.RLock() hasConfig := this.HasConfig current := this.Config - this.mu.RUnlock() + this.Mutex.RUnlock() if !hasConfig { StorageInst.useDefaultStorage() @@ -186,10 +186,10 @@ func (this *StorageClass) Init(config ...dto.StorageConfig) { conf := StorageInst.normConfig(current) - this.mu.Lock() + this.Mutex.Lock() this.Config = conf this.Hash = conf.Hash - this.mu.Unlock() + this.Mutex.Unlock() StorageInst.setActiveStorage(conf) diff --git a/go.mod b/go.mod index 7668fb7..1e04ad7 100644 --- a/go.mod +++ b/go.mod @@ -61,6 +61,8 @@ require ( github.com/tjfoc/gmsm v1.4.1 // indirect github.com/ulikunitz/xz v0.5.15 // indirect go.uber.org/atomic v1.11.0 // indirect + go.uber.org/multierr v1.10.0 // indirect + go.uber.org/zap v1.27.1 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect go4.org v0.0.0-20260112195520-a5071408f32f // indirect golang.org/x/net v0.51.0 // indirect @@ -68,4 +70,5 @@ require ( golang.org/x/time v0.14.0 // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect ) diff --git a/go.sum b/go.sum index bc034e6..618c71c 100644 --- a/go.sum +++ b/go.sum @@ -233,6 +233,10 @@ github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= +go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= +go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= go4.org v0.0.0-20260112195520-a5071408f32f h1:ziUVAjmTPwQMBmYR1tbdRFJPtTcQUI12fH9QQjfb0Sw= @@ -385,6 +389,8 @@ gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkp gopkg.in/ini.v1 v1.56.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/utils/validate.go b/utils/validate.go index bb65a68..2f4b666 100644 --- a/utils/validate.go +++ b/utils/validate.go @@ -3,10 +3,9 @@ package utils import ( "encoding/json" "errors" - "fmt" "reflect" "strings" - + "github.com/spf13/cast" ) @@ -156,7 +155,7 @@ func ValidateRules(name string, value any, rule string, message map[string]strin if msg == "" { msg = name + " length cannot be less than " + second + "!" } - return fmt.Errorf(msg) + return errors.New(msg) } case "max": // 判断长度是否大于最大值 @@ -165,7 +164,7 @@ func ValidateRules(name string, value any, rule string, message map[string]strin if msg == "" { msg = name + " length cannot be greater than " + second + "!" } - return fmt.Errorf(msg) + return errors.New(msg) } } @@ -178,7 +177,7 @@ func ValidateRules(name string, value any, rule string, message map[string]strin if msg == "" { msg = name + " is not empty!" } - return fmt.Errorf(msg) + return errors.New(msg) } case "email": if !Is.Email(value) { @@ -186,7 +185,7 @@ func ValidateRules(name string, value any, rule string, message map[string]strin if msg == "" { msg = name + " format is incorrect! Required in format!" } - return fmt.Errorf(msg) + return errors.New(msg) } case "number": if !Is.Number(value) { @@ -194,7 +193,7 @@ func ValidateRules(name string, value any, rule string, message map[string]strin if msg == "" { msg = name + " format is incorrect! Required in format!" } - return fmt.Errorf(msg) + return errors.New(msg) } case "float": if !Is.Float(value) { @@ -202,7 +201,7 @@ func ValidateRules(name string, value any, rule string, message map[string]strin if msg == "" { msg = name + " format is incorrect! Required in format!" } - return fmt.Errorf(msg) + return errors.New(msg) } case "bool": if !Is.Bool(value) { @@ -210,7 +209,7 @@ func ValidateRules(name string, value any, rule string, message map[string]strin if msg == "" { msg = name + " format is incorrect! Required in format!" } - return fmt.Errorf(msg) + return errors.New(msg) } case "slice": if !Is.Slice(value) { @@ -218,7 +217,7 @@ func ValidateRules(name string, value any, rule string, message map[string]strin if msg == "" { msg = name + " format is incorrect! Required in format!" } - return fmt.Errorf(msg) + return errors.New(msg) } case "jsonStr": if !Is.JsonString(value) { @@ -226,7 +225,7 @@ func ValidateRules(name string, value any, rule string, message map[string]strin if msg == "" { msg = name + " format is incorrect! Required in format!" } - return fmt.Errorf(msg) + return errors.New(msg) } case "accepted": if !Is.Accepted(value) { @@ -234,7 +233,7 @@ func ValidateRules(name string, value any, rule string, message map[string]strin if msg == "" { msg = name + " format is incorrect!" } - return fmt.Errorf(msg) + return errors.New(msg) } case "date": if !Is.Date(value) { @@ -242,7 +241,7 @@ func ValidateRules(name string, value any, rule string, message map[string]strin if msg == "" { msg = name + " format is incorrect! Required in format!" } - return fmt.Errorf(msg) + return errors.New(msg) } case "alpha": if !Is.Alpha(value) { @@ -250,7 +249,7 @@ func ValidateRules(name string, value any, rule string, message map[string]strin if msg == "" { msg = name + " format is incorrect!" } - return fmt.Errorf(msg) + return errors.New(msg) } case "alphaNum": if !Is.AlphaNum(value) { @@ -258,7 +257,7 @@ func ValidateRules(name string, value any, rule string, message map[string]strin if msg == "" { msg = name + " format is incorrect!" } - return fmt.Errorf(msg) + return errors.New(msg) } case "alphaDash": if !Is.AlphaDash(value) { @@ -266,7 +265,7 @@ func ValidateRules(name string, value any, rule string, message map[string]strin if msg == "" { msg = name + " format is incorrect!" } - return fmt.Errorf(msg) + return errors.New(msg) } case "chs": if !Is.Chs(value) { @@ -274,7 +273,7 @@ func ValidateRules(name string, value any, rule string, message map[string]strin if msg == "" { msg = name + " format is incorrect!" } - return fmt.Errorf(msg) + return errors.New(msg) } case "chsAlpha": if !Is.ChsAlpha(value) { @@ -282,7 +281,7 @@ func ValidateRules(name string, value any, rule string, message map[string]strin if msg == "" { msg = name + " format is incorrect!" } - return fmt.Errorf(msg) + return errors.New(msg) } case "chsAlphaNum": if !Is.ChsAlphaNum(value) { @@ -290,7 +289,7 @@ func ValidateRules(name string, value any, rule string, message map[string]strin if msg == "" { msg = name + " format is incorrect!" } - return fmt.Errorf(msg) + return errors.New(msg) } case "chsDash": if !Is.ChsDash(value) { @@ -298,7 +297,7 @@ func ValidateRules(name string, value any, rule string, message map[string]strin if msg == "" { msg = name + " format is incorrect!" } - return fmt.Errorf(msg) + return errors.New(msg) } case "cntrl": if !Is.Cntrl(value) { @@ -306,7 +305,7 @@ func ValidateRules(name string, value any, rule string, message map[string]strin if msg == "" { msg = name + " format is incorrect!" } - return fmt.Errorf(msg) + return errors.New(msg) } case "graph": if !Is.Graph(value) { @@ -314,7 +313,7 @@ func ValidateRules(name string, value any, rule string, message map[string]strin if msg == "" { msg = name + " format is incorrect!" } - return fmt.Errorf(msg) + return errors.New(msg) } case "lower": if !Is.Lower(value) { @@ -322,7 +321,7 @@ func ValidateRules(name string, value any, rule string, message map[string]strin if msg == "" { msg = name + " format is incorrect!" } - return fmt.Errorf(msg) + return errors.New(msg) } case "upper": if !Is.Upper(value) { @@ -330,7 +329,7 @@ func ValidateRules(name string, value any, rule string, message map[string]strin if msg == "" { msg = name + " format is incorrect!" } - return fmt.Errorf(msg) + return errors.New(msg) } case "space": if !Is.Space(value) { @@ -338,7 +337,7 @@ func ValidateRules(name string, value any, rule string, message map[string]strin if msg == "" { msg = name + " format is incorrect!" } - return fmt.Errorf(msg) + return errors.New(msg) } case "xdigit": if !Is.Xdigit(value) { @@ -346,7 +345,7 @@ func ValidateRules(name string, value any, rule string, message map[string]strin if msg == "" { msg = name + " format is incorrect!" } - return fmt.Errorf(msg) + return errors.New(msg) } case "activeUrl": if !Is.ActiveUrl(value) { @@ -354,7 +353,7 @@ func ValidateRules(name string, value any, rule string, message map[string]strin if msg == "" { msg = name + " format is incorrect!" } - return fmt.Errorf(msg) + return errors.New(msg) } case "url": if !Is.Url(value) { @@ -362,7 +361,7 @@ func ValidateRules(name string, value any, rule string, message map[string]strin if msg == "" { msg = name + " format is incorrect!" } - return fmt.Errorf(msg) + return errors.New(msg) } case "ip": if !Is.Ip(value) { @@ -370,7 +369,7 @@ func ValidateRules(name string, value any, rule string, message map[string]strin if msg == "" { msg = name + " format is incorrect!" } - return fmt.Errorf(msg) + return errors.New(msg) } case "mobile": if !Is.Mobile(value) { @@ -378,7 +377,7 @@ func ValidateRules(name string, value any, rule string, message map[string]strin if msg == "" { msg = name + " format is incorrect!" } - return fmt.Errorf(msg) + return errors.New(msg) } case "idCard": if !Is.IdCard(value) { @@ -386,7 +385,7 @@ func ValidateRules(name string, value any, rule string, message map[string]strin if msg == "" { msg = name + " format is incorrect!" } - return fmt.Errorf(msg) + return errors.New(msg) } case "MacAddr": if !Is.MacAddr(value) { @@ -394,7 +393,7 @@ func ValidateRules(name string, value any, rule string, message map[string]strin if msg == "" { msg = name + " format is incorrect!" } - return fmt.Errorf(msg) + return errors.New(msg) } case "zip": if !Is.Zip(value) { @@ -402,7 +401,7 @@ func ValidateRules(name string, value any, rule string, message map[string]strin if msg == "" { msg = name + " format is incorrect!" } - return fmt.Errorf(msg) + return errors.New(msg) } } }