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 }