go——–gin+mysql+redis+websocket搭建聊天

作者: adm 分类: go 发布时间: 2023-06-05

一、.环境准备

首先安装gin框架,官网根据文档安装操作

2.安装mysql驱动

go get -u gorm.io/driver/mysql

3.安装redis依赖

go get -u github.com/go-redis/redis/v8

4安装websocket依赖

go get github.com/gorilla/websocket

二、链接MySQL和redis

1.在根目录下新建config/config.yml如下

mysql:
  localhost: 127.0.0.1
  port: 3306
  username: root
  password: admin123
  database: ginchat
 
redis:
  host: 127.0.0.1
  port: 6379
  password:
  selectDb: 5
  polSize: 30
  minIdleConn: 30

2.untils目录下负责链接redis,mysql,kafak等操作,地址untils/system_init.go

/**
* Date: 2023/5/28
* Time: 下午 14:24
* Author: QY
 */
 
package untils
 
import (
	"context"
	"fmt"
	"github.com/go-redis/redis/v8"
	"github.com/spf13/viper"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"log"
	"os"
	"time"
 
	"gorm.io/driver/mysql"
)
 
//声明全局数据库链接
var DB *gorm.DB
var Red *redis.Client
 
// 读取mysql连接的配置参数
func InitConfig() (host string, database string, port string, username string, password string) {
	viper.SetConfigName("app")
	viper.AddConfigPath("config")
	err := viper.ReadInConfig()
	if err != nil {
		fmt.Printf("读取配置文件错误", err)
	}
	host = viper.GetString("mysql.localhost")
	database = viper.GetString("mysql.database")
	port = viper.GetString("mysql.port")
	username = viper.GetString("mysql.username")
	password = viper.GetString("mysql.password")
	return host, database, port, username, password
}
 
// 初始化连接mysql
func InitMySQL() {
	//自定义日志打印sql语句
	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags),
		logger.Config{
			SlowThreshold: time.Second, //慢SQL阈值
			LogLevel:      logger.Info, //级别
			Colorful:      true,        //彩色
		},
	)
	host, database, port, username, password := InitConfig()
	urlList := username + ":" + password + "@tcp(" + host + ":" + port + ")/" + database + "?charset=utf8mb4&parseTime=true&loc=Local"
	DB, _ = gorm.Open(mysql.Open(urlList), &gorm.Config{Logger: newLogger})
	fmt.Println(" MySQL inited 。。。。")
 
}
 
// 读取redis配置文件
func RedisConfig() (host string, selectDb int, port string, password string, polSize int, minIdleConn int) {
	viper.SetConfigName("app")
	viper.AddConfigPath("config")
	err := viper.ReadInConfig()
	if err != nil {
		fmt.Printf("读取redis配置文件错误", err)
	}
	host = viper.GetString("redis.host")
	selectDb = viper.GetInt("redis.selectDb")
	port = viper.GetString("redis.port")
	password = viper.GetString("redis.password")
	polSize = viper.GetInt("redis.polSize")
	minIdleConn = viper.GetInt("redis.minIdleConn")
	return host, selectDb, port, password, polSize, minIdleConn
}
 
// 初始化连接redis
func InitRedis() {
	host, selectDb, port, password, polSize, minIdleConn := RedisConfig()
	localhost := host + ":" + port
	fmt.Println("地址打印==:", localhost)
	Red = redis.NewClient(&redis.Options{
		Addr:         localhost,
		Password:     password,
		DB:           selectDb,
		PoolSize:     polSize,
		MinIdleConns: minIdleConn,
	})
	fmt.Println(" Redis inited 。。。。")
}
 
const (
	PublishKey = "websocket"
)
 
// 发起Publish 发消息到redis
func Publish(c context.Context, channel string, msg string) error {
	var err error
	err = Red.Publish(c, channel, msg).Err()
	return err
}
 
// Subscribe订阅redis消息
func Subscribe(c context.Context, channel string) (string, error) {
	sub := Red.PSubscribe(c, channel)
	fmt.Println("Subscribe。。。", sub)
	msg, err := sub.ReceiveMessage(c)
	return msg.Payload, err
}

3.main.go文件引用untils链接

package main
 
import (
	"fmt"
	"go-study/router"
	"go-study/untils"
)
 
func main() {
    //引用untils下的mysql和redis    
	untils.InitMySQL()
	untils.InitRedis()
	r := router.Router()
	r.Run(":8081")
 
}

三、搭建websocket骨架

1.在控制器层新建如下

// 防止跨域站点为找请求
var upGrade = websocket.Upgrader{
	CheckOrigin: func(r *http.Request) bool {
		return true
	},
}
 
//消息发送
func SendMsg(c *gin.Context) {
	ws, err := upGrade.Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		fmt.Println("ws数据打印", err)
		return
	}
	defer func(ws *websocket.Conn) {
		err = ws.Close()
		if err != nil {
			fmt.Println("错误的ws日志打印")
		}
	}(ws)
	MsgHandler(ws, c)
}
 
// 消息中间件
func MsgHandler(ws *websocket.Conn, c context.Context) {
	msg, err := untils.Subscribe(c, untils.PublishKey)
	if err != nil {
		fmt.Println("错误打印", err)
	}
	tm := time.Now().Format("2006-01-02 15:04:05")
	m := fmt.Sprintf("[ws][%s]:%s", tm, msg)
	err = ws.WriteMessage(1, []byte(m))
	if err != nil {
		fmt.Println("消息异常打印", err)
	}
 
}

3.将控制器层加入到路由

/**
* Date: 2023/5/28
* Time: 下午 14:24
* Author: QY
 */
 
package router
 
func Router() *gin.Engine {
	r := gin.Default()
	docs.SwaggerInfo.BasePath = ""
	r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerfiles.Handler))
	r.GET("/user/sendMsg", controller.SendMsg)
	return r
}

如果觉得我的文章对您有用,请随意赞赏。您的支持将鼓励我继续创作!