refactor: 重构代码架构并使用 Modern Go 特性

- 重命名模块 jwts -> schedule_converter
- 新增 service 包,统一业务逻辑层
- 新增 pkg/logger 包,使用 slog 结构化日志
- 新增 pkg/errors 包,统一错误处理
- 拆分 captcha 包,图片识别移至 service/recognizer
- 清理 models 包,只保留数据结构定义
- 消除 grpc/handler.go 中的重复代码
- 简化 main.go,使用 slog 和 context
- 配置支持单例模式和结构化配置
- 使用 any 替代 interface{}
- 使用 sync.Map 替代 map + RWMutex
This commit is contained in:
lafay
2026-03-16 13:40:53 +08:00
parent 294151cd40
commit 74438c1f7f
20 changed files with 1183 additions and 602 deletions

58
pkg/errors/errors.go Normal file
View File

@@ -0,0 +1,58 @@
package errors
import (
"errors"
"fmt"
)
var (
ErrInvalidConfig = errors.New("invalid configuration")
ErrLoginFailed = errors.New("login failed")
ErrCaptchaFailed = errors.New("captcha recognition failed")
ErrScheduleFailed = errors.New("failed to fetch schedule")
ErrRecognitionFailed = errors.New("schedule recognition failed")
ErrUnauthorized = errors.New("unauthorized access")
ErrTimeout = errors.New("operation timeout")
ErrConnectionFailed = errors.New("connection failed")
)
type ScheduleError struct {
Op string
Err error
Msg string
}
func (e *ScheduleError) Error() string {
if e.Msg != "" {
return fmt.Sprintf("%s: %s: %v", e.Op, e.Msg, e.Err)
}
return fmt.Sprintf("%s: %v", e.Op, e.Err)
}
func (e *ScheduleError) Unwrap() error {
return e.Err
}
func New(op string, err error, msg string) error {
return &ScheduleError{
Op: op,
Err: err,
Msg: msg,
}
}
func Wrap(err error, msg string) error {
return fmt.Errorf("%s: %w", msg, err)
}
func Join(errs ...error) error {
return errors.Join(errs...)
}
func Is(err, target error) bool {
return errors.Is(err, target)
}
func As(err error, target any) bool {
return errors.As(err, target)
}

55
pkg/logger/logger.go Normal file
View File

@@ -0,0 +1,55 @@
package logger
import (
"log/slog"
"os"
)
var (
defaultLevel = slog.LevelInfo
logger *slog.Logger
)
func init() {
opts := &slog.HandlerOptions{
Level: defaultLevel,
}
logger = slog.New(slog.NewJSONHandler(os.Stdout, opts))
slog.SetDefault(logger)
}
func SetLevel(level slog.Level) {
opts := &slog.HandlerOptions{
Level: level,
}
logger = slog.New(slog.NewJSONHandler(os.Stdout, opts))
slog.SetDefault(logger)
}
func SetTextHandler() {
opts := &slog.HandlerOptions{
Level: defaultLevel,
}
logger = slog.New(slog.NewTextHandler(os.Stdout, opts))
slog.SetDefault(logger)
}
func Debug(msg string, args ...any) {
slog.Debug(msg, args...)
}
func Info(msg string, args ...any) {
slog.Info(msg, args...)
}
func Warn(msg string, args ...any) {
slog.Warn(msg, args...)
}
func Error(msg string, args ...any) {
slog.Error(msg, args...)
}
func With(args ...any) *slog.Logger {
return slog.With(args...)
}