feat(*): go 后端项目脚手架

This commit is contained in:
2025-11-15 18:20:30 +08:00
commit 5bb025c1aa
39 changed files with 2459 additions and 0 deletions

25
pkg/db/connect.go Normal file
View File

@@ -0,0 +1,25 @@
package db
import (
"github.com/glebarez/sqlite"
"gorm.io/driver/mysql"
"gorm.io/driver/postgres"
"gorm.io/driver/sqlserver"
"gorm.io/gorm"
)
func connectMySQL(dsn string) gorm.Dialector {
return mysql.Open(dsn)
}
func connectSQLite(filepath string) gorm.Dialector {
return sqlite.Open(filepath + "?cache=shared&_fk=1&_driver=modernc.org/sqlite")
}
func connectPostgres(dsn string) gorm.Dialector {
return postgres.Open(dsn)
}
func connectSQLServer(dsn string) gorm.Dialector {
return sqlserver.Open(dsn)
}

64
pkg/db/db.go Normal file
View File

@@ -0,0 +1,64 @@
package db
import (
"fmt"
"os"
"github.com/zhilv666/navsite/pkg/config"
"go.uber.org/zap"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
var db *gorm.DB
func init() {
if _, err := os.Stat("./data"); os.IsNotExist(err) {
_ = os.Mkdir("./data", os.ModePerm)
}
}
func GetDB() *gorm.DB {
if db == nil {
panic("数据库未初始化,请先调用 db.InitDB()")
}
return db
}
func InitDB(cfg config.Database, log *zap.Logger) {
go func() {
if err := recover(); err != nil {
panic(fmt.Sprintf("Init DB Error: %v", err))
}
}()
var dsn string
var dialector gorm.Dialector
switch cfg.Driver {
case "mysql":
dsn = fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local",
cfg.User, cfg.Password, cfg.Host, cfg.Port, cfg.DbName)
dialector = connectMySQL(dsn)
case "postgres":
dsn = fmt.Sprintf("host=%s port=%d user=%s dbname=%s password=%s sslmode=disable",
cfg.Host, cfg.Port, cfg.User, cfg.DbName, cfg.Password)
dialector = connectPostgres(dsn)
case "sqlserver":
dsn = fmt.Sprintf("sqlserver://%s:%s@%s:%d?database=%s",
cfg.User, cfg.Password, cfg.Host, cfg.Port, cfg.DbName)
dialector = connectSQLServer(dsn)
case "sqlite", "sqlite3":
fmt.Println(cfg.SqliteDbPath)
dialector = connectSQLite(cfg.SqliteDbPath)
default:
panic(fmt.Errorf("unsupport database driver: %s", cfg.Driver))
}
var err error
db, err = gorm.Open(dialector, &gorm.Config{
Logger: NewZapGormLogger(log).LogMode(logger.Info),
})
if err != nil {
panic(err)
}
}

81
pkg/db/gorm_logger.go Normal file
View File

@@ -0,0 +1,81 @@
package db
import (
"context"
"time"
"go.uber.org/zap"
"gorm.io/gorm/logger"
"gorm.io/gorm/utils"
)
type ZapGormLogger struct {
ZapLogger *zap.Logger
LogLevel logger.LogLevel
SlowThreshold time.Duration
}
func NewZapGormLogger(zapLogger *zap.Logger) *ZapGormLogger {
return &ZapGormLogger{
ZapLogger: zapLogger,
LogLevel: logger.Info,
SlowThreshold: time.Second, // 1s 慢查询阈值
}
}
func (l *ZapGormLogger) LogMode(level logger.LogLevel) logger.Interface {
newlogger := *l
newlogger.LogLevel = level
return &newlogger
}
func (l *ZapGormLogger) Info(ctx context.Context, msg string, data ...interface{}) {
if l.LogLevel >= logger.Info {
l.ZapLogger.Sugar().Infof(msg, data...)
}
}
func (l *ZapGormLogger) Warn(ctx context.Context, msg string, data ...interface{}) {
if l.LogLevel >= logger.Warn {
l.ZapLogger.Sugar().Warnf(msg, data...)
}
}
func (l *ZapGormLogger) Error(ctx context.Context, msg string, data ...interface{}) {
if l.LogLevel >= logger.Error {
l.ZapLogger.Sugar().Errorf(msg, data...)
}
}
func (l *ZapGormLogger) Trace(ctx context.Context, begin time.Time, fc func() (sql string, rowsAffected int64), err error) {
if l.LogLevel <= logger.Silent {
return
}
elapsed := time.Since(begin)
sql, rows := fc()
switch {
case err != nil && l.LogLevel >= logger.Error:
l.ZapLogger.Error("SQL Error",
zap.Error(err),
zap.String("sql", sql),
zap.Int64("rows", rows),
zap.Duration("elapsed", elapsed),
zap.String("file", utils.FileWithLineNum()),
)
case elapsed > l.SlowThreshold && l.SlowThreshold != 0 && l.LogLevel >= logger.Warn:
l.ZapLogger.Warn("Slow SQL",
zap.Duration("elapsed", elapsed),
zap.String("sql", sql),
zap.Int64("rows", rows),
zap.String("file", utils.FileWithLineNum()),
)
case l.LogLevel >= logger.Info:
l.ZapLogger.Info("SQL",
zap.String("sql", sql),
zap.Int64("rows", rows),
zap.Duration("elapsed", elapsed),
zap.String("file", utils.FileWithLineNum()),
)
}
}