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

初始化配置

文章目录

一、配置yaml文件

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.结构体的定义

go 复制代码
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.从指定路径中读取配置信息到结构体里面

go 复制代码
// 定义一个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的结构化日志库。故使用轻量级的日志库。

go 复制代码
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)

go 复制代码
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)

go 复制代码
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.跨域请求

go 复制代码
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键上

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

3.绑定Redis

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

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

go 复制代码
func WithCookieStore(name, secret string) gin.HandlerFunc {
	store := cookie.NewStore([]byte(secret))
	store.Options(sessions.Options{Path: "/", MaxAge: 600})
	return sessions.Sessions(name, store)
}
相关推荐
阿华的代码王国25 分钟前
MySQL ------- 索引(B树B+树)
数据库·mysql
码爸1 小时前
flink 批量压缩redis集群 sink
大数据·redis·flink
liupenglove1 小时前
golang操作mysql利器-gorm
mysql·golang
叫我:松哥1 小时前
基于Python flask的医院管理学院,医生能够增加/删除/修改/删除病人的数据信息,有可视化分析
javascript·后端·python·mysql·信息可视化·flask·bootstrap
微刻时光2 小时前
Redis集群知识及实战
数据库·redis·笔记·学习·程序人生·缓存
单字叶2 小时前
MySQL数据库
数据库·mysql
just-julie2 小时前
MySQL面试题——第一篇
数据库·mysql
Rookie_explorers2 小时前
Linux下go环境安装、环境配置并执行第一个go程序
linux·运维·golang
做技术的Pandaer2 小时前
Go 第二期
开发语言·golang
丁总学Java2 小时前
如何使用 maxwell 同步到 redis?
数据库·redis·缓存