go——–gin+mysql+redis+websocket搭建聊天
一、.环境准备
首先安装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
}

