From d208872845648ae1a8c67ce2c4b28bea1619a4c7 Mon Sep 17 00:00:00 2001 From: xinzf Date: Thu, 23 Feb 2023 15:03:35 +0800 Subject: [PATCH] Update readme.md Add some wheels --- README.md | 2 +- documents/imgs/banner.jpeg | Bin 0 -> 37204 bytes go.mod | 1 + pkg/LogBuilder/log_info_array.go | 15 +++++++ pkg/LogBuilder/log_info_builder.go | 69 +++++++++++++++++++++++++++++ pkg/LogBuilder/logger.go | 56 +++++++++++++++++++++++ pkg/LogBuilder/logger_test.go | 17 +++++++ pkg/LogBuilder/misc.go | 27 +++++++++++ pkg/ParamsValidator/init.go | 51 +++++++++++++++++++++ pkg/ParamsValidator/init_test.go | 35 +++++++++++++++ 10 files changed, 272 insertions(+), 1 deletion(-) create mode 100644 documents/imgs/banner.jpeg create mode 100644 pkg/LogBuilder/log_info_array.go create mode 100644 pkg/LogBuilder/log_info_builder.go create mode 100644 pkg/LogBuilder/logger.go create mode 100644 pkg/LogBuilder/logger_test.go create mode 100644 pkg/LogBuilder/misc.go create mode 100644 pkg/ParamsValidator/init.go create mode 100644 pkg/ParamsValidator/init_test.go diff --git a/README.md b/README.md index 4dd8a2de..dd065db0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![image-20230223111012814](https://baize-blog-images.oss-cn-shanghai.aliyuncs.com/img/image-20230223111012814.png) +![image-20230223111012814](./documents/imgs/banner.jpeg) DouTok is a backend for TikTok client based on Kitex and Hertz. diff --git a/documents/imgs/banner.jpeg b/documents/imgs/banner.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..78dd85d16e84437e19a5e379c6c11296dd1cd3b3 GIT binary patch literal 37204 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 Reg8ie)c-H<3I1pDe*q%3IJ^J= literal 0 HcmV?d00001 diff --git a/go.mod b/go.mod index 1aa45ede..56203fe9 100644 --- a/go.mod +++ b/go.mod @@ -35,6 +35,7 @@ require ( go.uber.org/zap v1.24.0 golang.org/x/net v0.7.0 google.golang.org/protobuf v1.28.1 + gopkg.in/natefinch/lumberjack.v2 v2.0.0 gopkg.in/yaml.v3 v3.0.1 gorm.io/driver/mysql v1.4.5 gorm.io/gen v0.3.20 diff --git a/pkg/LogBuilder/log_info_array.go b/pkg/LogBuilder/log_info_array.go new file mode 100644 index 00000000..766ce84b --- /dev/null +++ b/pkg/LogBuilder/log_info_array.go @@ -0,0 +1,15 @@ +package LogBuilder + +type logInfoArray []*logInfo + +func (arr logInfoArray) Len() int { + return len(arr) +} + +func (arr logInfoArray) Less(i, j int) bool { + return arr[i].key < arr[j].key +} + +func (arr logInfoArray) Swap(i, j int) { + arr[i], arr[j] = arr[j], arr[i] +} diff --git a/pkg/LogBuilder/log_info_builder.go b/pkg/LogBuilder/log_info_builder.go new file mode 100644 index 00000000..77beaa2d --- /dev/null +++ b/pkg/LogBuilder/log_info_builder.go @@ -0,0 +1,69 @@ +package LogBuilder + +import ( + "fmt" + "sort" +) + +type LogInfoBuilder struct { + logType string + message string + Items map[string]string +} + +func InitLogBuilder() *LogInfoBuilder { + return &LogInfoBuilder{ + Items: make(map[string]string), + } +} + +func (b *LogInfoBuilder) SetLogType(typeString string) { + b.logType = typeString +} + +func (b *LogInfoBuilder) SetMessage(str string) { + b.message = str +} + +func (b *LogInfoBuilder) Collect(key string, value string) { + tempKey := key + + _, ok := b.Items[tempKey] + if ok { + cnt := 1 + for { + _, ok := b.Items[tempKey+fmt.Sprint(cnt)] + if !ok { + tempKey = tempKey + fmt.Sprint(cnt) + break + } + cnt++ + } + } + + b.Items[tempKey] = value +} + +func (b *LogInfoBuilder) Get() []string { + temp := []*logInfo{} + + for k, v := range b.Items { + newLogInfo := logInfo{ + key: k, + value: v, + } + temp = append(temp, &newLogInfo) + } + + sort.Sort(logInfoArray(temp)) + res := []string{} + for _, v := range temp { + res = append(res, v.key) + res = append(res, v.value) + } + return res +} + +func (b *LogInfoBuilder) Write(logger *Logger) { + logger.Write(b.logType, b.message, b.Get()...) +} diff --git a/pkg/LogBuilder/logger.go b/pkg/LogBuilder/logger.go new file mode 100644 index 00000000..db94e6aa --- /dev/null +++ b/pkg/LogBuilder/logger.go @@ -0,0 +1,56 @@ +package LogBuilder + +import ( + "go.uber.org/zap" + "go.uber.org/zap/zapcore" +) + +type Logger struct { + Handle *zap.Logger +} + +type logInfo struct { + key string + value string +} + +func New(filename string, maxSize int, maxBackups int, maxAge int) *Logger { + writeSyncer := getLogWriter( + filename, maxSize, maxBackups, maxAge, + ) + + encoder := getEncoder() + + var l = new(zapcore.Level) + if err := l.UnmarshalText([]byte("info")); err != nil { + panic(err) + } + core := zapcore.NewCore(encoder, writeSyncer, l) + + logger := zap.New(core, zap.AddCaller(), zap.AddCallerSkip(1)) + return &Logger{ + Handle: logger, + } +} + +func (l *Logger) Write(logType string, msg string, values ...string) { + if len(values)%2 != 0 { + panic("日志信息的键与值数量不匹配") + } + + logInfo := make([]zapcore.Field, len(values)/2) + for i := 0; i < len(values); i += 2 { + logInfo[i/2] = zap.String(values[i], values[i+1]) + } + + switch logType { + case "info": + l.Handle.Info(msg, logInfo...) + case "error": + l.Handle.Error(msg, logInfo...) + case "warn": + l.Handle.Warn(msg, logInfo...) + default: + l.Handle.Info(msg, logInfo...) + } +} diff --git a/pkg/LogBuilder/logger_test.go b/pkg/LogBuilder/logger_test.go new file mode 100644 index 00000000..04255c50 --- /dev/null +++ b/pkg/LogBuilder/logger_test.go @@ -0,0 +1,17 @@ +package LogBuilder + +import "testing" + +func TestLogger(t *testing.T) { + logger := New("./temp.log", 1024*1024, 3, 10) + + log := InitLogBuilder() + log.SetLogType("error") + log.SetMessage("Test log info") + log.Collect("key1", "value1") + log.Collect("key2", "value2") + log.Collect("key2", "value2") + log.Collect("key3", "value3") + + log.Write(logger) +} diff --git a/pkg/LogBuilder/misc.go b/pkg/LogBuilder/misc.go new file mode 100644 index 00000000..e290dced --- /dev/null +++ b/pkg/LogBuilder/misc.go @@ -0,0 +1,27 @@ +package LogBuilder + +import ( + "go.uber.org/zap" + "go.uber.org/zap/zapcore" + "gopkg.in/natefinch/lumberjack.v2" +) + +func getEncoder() zapcore.Encoder { + encoderConfig := zap.NewProductionEncoderConfig() + encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder + encoderConfig.TimeKey = "time" + encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder + encoderConfig.EncodeDuration = zapcore.SecondsDurationEncoder + encoderConfig.EncodeCaller = zapcore.ShortCallerEncoder + return zapcore.NewJSONEncoder(encoderConfig) +} + +func getLogWriter(filename string, maxSize, maxBackup, maxAge int) zapcore.WriteSyncer { + lumberJackLogger := &lumberjack.Logger{ + Filename: filename, + MaxSize: maxSize, + MaxBackups: maxBackup, + MaxAge: maxAge, + } + return zapcore.AddSync(lumberJackLogger) +} diff --git a/pkg/ParamsValidator/init.go b/pkg/ParamsValidator/init.go new file mode 100644 index 00000000..a594b0a5 --- /dev/null +++ b/pkg/ParamsValidator/init.go @@ -0,0 +1,51 @@ +package ParamsValidator + +import "github.com/TremblingV5/DouTok/pkg/errno" + +type Rule struct { + Result bool + Message *errno.ErrNo + Ops []func() (bool, *errno.ErrNo) + Index int +} + +func New(message *errno.ErrNo) *Rule { + return &Rule{ + Result: true, + Message: message, + Ops: []func() (bool, *errno.ErrNo){}, + Index: 0, + } +} + +func (r *Rule) Set(f func() (bool, *errno.ErrNo)) *Rule { + r.Ops = append(r.Ops, f) + return r +} + +func (r *Rule) SetMore(f ...func() (bool, *errno.ErrNo)) *Rule { + for _, v := range f { + r.Ops = append(r.Ops, v) + } + return r +} + +func (r *Rule) Next() bool { + if r.Index < len(r.Ops) { + result, errNo := r.Ops[r.Index]() + r.Result = r.Result && result + r.Index++ + if r.Result { + return r.Next() + } else { + r.Message = errNo + return false + } + } else { + return r.Result + } +} + +func (r *Rule) Validate() (bool, *errno.ErrNo) { + return r.Next(), r.Message +} diff --git a/pkg/ParamsValidator/init_test.go b/pkg/ParamsValidator/init_test.go new file mode 100644 index 00000000..24f6fd9a --- /dev/null +++ b/pkg/ParamsValidator/init_test.go @@ -0,0 +1,35 @@ +package ParamsValidator + +import ( + "github.com/TremblingV5/DouTok/pkg/errno" + "log" + "testing" +) + +var success = errno.NewErrNo(0, "Success") +var usernameErr = errno.NewErrNo(1, "usernameErr") +var passwordErr = errno.NewErrNo(2, "passwordErr") + +func TestValidate(t *testing.T) { + username := "xinzf" + password := "123456" + + validator := New(&success) + validator.Set(func() (bool, *errno.ErrNo) { + if len(username) < 10 { + return false, &usernameErr + } else { + return true, &success + } + }).Set(func() (bool, *errno.ErrNo) { + if len(password) < 6 { + return false, &passwordErr + } else { + return true, &success + } + }) + + ok, errNo := validator.Validate() + log.Println(ok) + log.Println(errNo) +}