(二)Go的Mysql、Redis、Cookie、Logger等的文件配置

初始化配置

在这里插入图片描述

一、配置yaml文件

Server:
  Mode: debug # 服务器模式,可选值为 debug 或 release
  Port: :8765 # 服务器端口号
  DbType: "mysql" # 数据库类型,可选值为 mysql 或 sqlite
  DbAutoMigrate: true # 是否自动迁移数据库表结构,如果表结构没有变化,可以设为 false 提高启动速度
  DbLogMode: "error" # 数据库日志级别,可选值有 silent, error, warn, info, 默认为 info

JWT: # JWT 鉴权配置
  Secret: "abc123321" # JWT 密钥
  Expire: 24 # JWT 过期时间,单位为小时
  Issuer: "gin-vue-blog" # JWT 签发者

Mysql: # MySQL 数据库配置
  Host: "127.0.0.1" # MySQL 主机地址
  Port: "3306" # MySQL 端口号
  Config: "charset=utf8mb4&parseTime=True&loc=Local" # MySQL 配置,例如字符集和时区设置
  Dbname: "gvb" # MySQL 数据库名称
  Username: "root" # MySQL 用户名
  Password: "123456" # MySQL 密码

Sqlite: # SQLite 数据库配置
  Dsn: "gvb.db" # SQLite 数据库文件路径

Redis: # Redis 缓存配置
  DB: 0 # Redis 数据库索引
  Addr: '' # Redis 服务器地址
  Password: '' # Redis 访问密码,如果没有设置密码则留空

Session: # 会话(Session)配置
  Name: "mysession" # 会话名称
  Salt: "salt" # 加密盐
  MaxAge: 600 # 会话过期时间,单位为秒

Log: # 日志配置
  Level: "debug" # 日志级别,可选值有 debug, info, warn, error
  Format: "text" # 日志格式,可选值有 text, json
  Directory: "log" # 日志存储目录

Email: # 邮件发送配置
  Host: "smtp.qq.com" # SMTP 服务器地址
  Port: 465 # SMTP 服务器端口号
  From: "" # 发件人邮箱
  IsSSL: true # 是否开启 SSL
  Secret: "" # SMTP 密钥
  Nickname: "" # 发件人昵称

Captcha: # 验证码配置
  SendEmail: true # 是否通过邮件发送验证码
  ExpireTime: 5  # 验证码过期时间,单位为分钟

Upload: # 文件上传配置
  OssType: "qiniu" # 文件上传类型,可选值为 local 或 qiniu
  Path: "public/uploaded" # 本地文件访问路径,OssType="local" 生效
  StorePath: "../public/uploaded" # 本地文件上传路径,相对于 main.go,OssType="local" 生效

Qiniu: # 七牛云存储配置
  ImgPath: "" # 外链
  Zone: "z1" # 存储区域,可选值有 z0, z1, z2, na0, as0
  Bucket: "" # 存储空间名称
  AccessKey: "-" # 七牛云 AccessKey
  SecretKey: "" # 七牛云 SecretKey
  UseHttps: false # 是否使用 HTTPS 协议进行图片上传和访问
  UseCdnDomains: false # 是否使用七牛云 CDN 加速域名

二、Go读取配置文件

1.结构体的定义

type Config struct {
	Server struct {
		Mode          string // debug | release
		Port          string
		DbType        string // mysql | sqlite
		DbAutoMigrate bool   // 是否自动迁移数据库表结构
		DbLogMode     string // silent | error | warn | info
	}
	Log struct {
		Level     string // debug | info | warn | error
		Prefix    string
		Format    string // text | json
		Directory string
	}
	JWT struct {
		Secret string
		Expire int64 // hour
		Issuer string
	}
	Mysql struct {
		Host     string // 服务器地址
		Port     string // 端口
		Config   string // 高级配置
		Dbname   string // 数据库名
		Username string // 数据库用户名
		Password string // 数据库密码
	}
	SQLite struct {
		Dsn string // Data Source Name
	}
	Redis struct {
		DB       int    // 指定 Redis 数据库
		Addr     string // 服务器地址:端口
		Password string // 密码
	}
	Session struct {
		Name   string
		Salt   string
		MaxAge int
	}
	Email struct {
		To       string // 收件人 多个以英文逗号分隔 例:a@qq.com,b@qq.com
		From     string // 发件人 要发邮件的邮箱
		Host     string // 服务器地址, 例如 smtp.qq.com 前往要发邮件的邮箱查看其 smtp 协议
		Secret   string // 密钥, 不是邮箱登录密码, 是开启 smtp 服务后获取的一串验证码
		Nickname string // 发件人昵称, 通常为自己的邮箱名
		Port     int    // 前往要发邮件的邮箱查看其 smtp 协议端口, 大多为 465
		IsSSL    bool   // 是否开启 SSL
	}
	Captcha struct {
		SendEmail  bool // 是否通过邮箱发送验证码
		ExpireTime int  // 过期时间
	}
	Upload struct {
		// Size      int    // 文件上传的最大值
		OssType   string // local | qiniu
		Path      string // 本地文件访问路径
		StorePath string // 本地文件存储路径
	}
	Qiniu struct {
		ImgPath       string // 外链链接
		Zone          string // 存储区域
		Bucket        string // 空间名称
		AccessKey     string // 秘钥AK
		SecretKey     string // 秘钥SK
		UseHTTPS      bool   // 是否使用https
		UseCdnDomains bool   // 上传是否使用 CDN 上传加速
	}
}

2.从指定路径中读取配置信息到结构体里面

// 定义一个Public的变量
var Conf *Config

func GetConfig() *Config {
	if Conf == nil {
		log.Panic("配置文件未初始化")
		return nil
	}
	return Conf
}

// 从指定路径读取配置文件
func ReadConfig(path string) *Config {
	v := viper.New()
	v.SetConfigFile(path)
	v.AutomaticEnv()                                   // 允许使用环境变量
	v.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) // SERVER_APPMODE => SERVER.APPMODE

	if err := v.ReadInConfig(); err != nil {
		panic("配置文件读取失败: " + err.Error())
	}

	if err := v.Unmarshal(&Conf); err != nil {
		panic("配置文件反序列化失败: " + err.Error())
	}

	log.Println("配置文件内容加载成功: ", path)
	return Conf
}

// 数据库类型
func (*Config) DbType() string {
	if Conf.Server.DbType == "" {
		Conf.Server.DbType = "sqlite"
	}
	return Conf.Server.DbType
}

// 数据库连接字符串
func (*Config) DbDSN() string {
	switch Conf.Server.DbType {
	case "mysql":
		conf := Conf.Mysql
		return fmt.Sprintf(
			"%s:%s@tcp(%s:%s)/%s?%s",
			conf.Username, conf.Password, conf.Host, conf.Port, conf.Dbname, conf.Config,
		)
	case "sqlite":
		return Conf.SQLite.Dsn
	// 默认使用 sqlite, 并且使用内存数据库
	default:
		Conf.Server.DbType = "sqlite"
		if Conf.SQLite.Dsn == "" {
			Conf.SQLite.Dsn = "file::memory:"
		}
		return Conf.SQLite.Dsn
	}
}

三、初始化日志Logger

在1.21.0版本后,go添加了slog的结构化日志库。故使用轻量级的日志库。

func InitLogger(conf *g.Config) *slog.Logger {
	var level slog.Level
	// 设置日志级别
	switch conf.Log.Level {
	case "debug":
		level = slog.LevelDebug
	case "info":
		level = slog.LevelInfo
	case "warn":
		level = slog.LevelWarn
	case "error":
		level = slog.LevelError
	default:
		level = slog.LevelInfo
	}

	option := &slog.HandlerOptions{
		AddSource: true, // 是否显示代码详细位置
		Level:     level,
		ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
			if a.Key == slog.TimeKey {
				if t, ok := a.Value.Any().(time.Time); ok {
					a.Value = slog.StringValue(t.Format(time.DateTime))
				}
			}
			return a
		},
	}

	var handler slog.Handler
	switch conf.Log.Format {
	case "json":
		handler = slog.NewJSONHandler(os.Stdout, option)
	case "text":
		fallthrough
	default: //默认text
		handler = slog.NewTextHandler(os.Stdout, option)
	}

	loggers := slog.New(handler)
	slog.SetDefault(loggers)
	return loggers
}

四、初始化数据库(MySQL或SqlLite)

func InitDatabase(conf *g.Config) *gorm.DB {
	dbtype := conf.DbType() // 数据库类型
	dsn := conf.DbDSN()     //DSN

	var db *gorm.DB
	var err error

	var level logger.LogLevel
	switch conf.Server.DbLogMode {
	case "silent":
		level = logger.Silent
	case "info":
		level = logger.Info
	case "warn":
		level = logger.Warn
	case "error":
		fallthrough
	default:
		level = logger.Error
	}

	config := &gorm.Config{
		Logger:                                   logger.Default.LogMode(level),
		DisableForeignKeyConstraintWhenMigrating: true, // 禁用外键约束
		SkipDefaultTransaction:                   true, // 禁用默认事务(提高运行速度)
		NamingStrategy: schema.NamingStrategy{
			SingularTable: true, // 单数表名
		},
	}

	switch dbtype {
	case "mysql":
		db, err = gorm.Open(mysql.Open(dsn), config)
	case "sqlite":
		db, err = gorm.Open(sqlite.Open(dsn), config)
	default:
		log.Fatal("不支持的数据库类型: ", dbtype)
	}

	if err != nil {
		log.Fatal("数据库连接失败", err)
	}
	log.Println("数据库连接成功", dbtype, dsn)

	if conf.Server.DbAutoMigrate {
		if err := model.MakeMigrate(db); err != nil {
			log.Fatal("数据库迁移失败", err)
		}
		log.Println("数据库自动迁移成功")
	}

	return db
}

五、初始化缓存(Redis)

func InitRedis(conf *g.Config) *redis.Client {
	rdb := redis.NewClient(&redis.Options{
		Addr:     conf.Redis.Addr,
		Password: conf.Redis.Password,
		DB:       conf.Redis.DB,
	})

	_, err := rdb.Ping(context.Background()).Result()
	if err != nil {
		log.Fatal("Redis 连接失败: ", err)
	}

	log.Println("Redis 连接成功", conf.Redis.Addr, conf.Redis.DB, conf.Redis.Password)
	return rdb
}

六、中间件服务(middleware)

1.跨域请求

func CORS() gin.HandlerFunc {
	return cors.New(cors.Config{
		AllowOrigins:     []string{"*"},
		AllowMethods:     []string{"PUT", "POST", "GET", "DELETE", "OPTIONS", "PATCH"},
		AllowHeaders:     []string{"Origin", "Authorization", "Content-Type", "X-Requested-With"},
		ExposeHeaders:    []string{"Content-Type"},
		AllowCredentials: true,
		AllowOriginFunc: func(origin string) bool {
			return true
		},
		MaxAge: 24 * time.Hour,
	})
}

2.绑定db,将*gorm.DB绑定到context的g.CTX_DB键上

func WithGormDB(db *gorm.DB) gin.HandlerFunc {
	return func(ctx *gin.Context) {
		ctx.Set(g.CTX_DB, db)
		ctx.Next()
	}
}

3.绑定Redis

func WithRedisDB(rdb *redis.Client) gin.HandlerFunc {
	return func(ctx *gin.Context) {
		ctx.Set(g.CTX_RDB, rdb)
		ctx.Next()
	}
}

4.设置cookie,用于在请求和响应之间存储会话信息

func WithCookieStore(name, secret string) gin.HandlerFunc {
	store := cookie.NewStore([]byte(secret))
	store.Options(sessions.Options{Path: "/", MaxAge: 600})
	return sessions.Sessions(name, store)
}
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

席万里

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值