(二)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)
}
相关推荐
weixin_4481199424 分钟前
Datawhale Hello-Agents入门篇202512第1次作业
数据库·sql·mysql
皮皮林55125 分钟前
有了开源的 MySQL,为什么还要选择 PostgreSQL?
mysql
廋到被风吹走2 小时前
【数据库】【MySQL】分库分表策略 分类、优势与短板
数据库·mysql·分类
嘻哈baby2 小时前
Redis高可用部署与集群管理实战
数据库·redis·bootstrap
五阿哥永琪3 小时前
MySQL 慢查询定位与 SQL 性能优化实战指南
sql·mysql·性能优化
Java爱好狂.4 小时前
Java面试Redis核心知识点整理!
java·数据库·redis·分布式锁·java面试·后端开发·java八股文
zfj3215 小时前
vscode是js开发的,为什么能支持golang java等各种语言开发
javascript·vscode·golang
阿杆5 小时前
如何在 Spring Boot 中接入 Amazon ElastiCache
java·数据库·redis
serendipity_hky6 小时前
【go语言 | 第5篇】channel——多个goroutine之间通信
开发语言·后端·golang
源代码•宸6 小时前
分布式缓存-GO(简历写法、常见面试题)
服务器·开发语言·经验分享·分布式·后端·缓存·golang