add frameworks support 没有web_Golang+Vue实现Web聊天室

Golang+Vue实现Web聊天室:轻量级框架选择与实现
本文介绍了如何使用Golang和Vue.js开发一个Web聊天室。选择Golang作为后端语言,因其简洁、高效、并发支持良好,尽管Go的框架支持较少,但内置库强大。前端选择了Vue.js,利用其简洁高效的特点。通讯通过WebSocket实现,后端采用Gin框架简化HTTP请求。文章提供了部分核心代码示例,完整源码可按需获取。

开发背景

——————

现有的业务系统需要基于某个业务主题及时应答客户问题,并存储关键信息,方便日后查询。虽然有微信聊天,但生活主题与业务数据混杂在一起,也不能长期存储查询。因此,需要在业务系统上挂载聊天室,提高实时办公和持久化、查询功能

先概览一下开发环境的效果:

3987b0d1594e734cfdebcd09fa440428.png

3d4a3c204abeb260aaa1a7e553ac88d7.png

d7ff90e4d82fed7168a5029fdad220ad.png

技术选型

——————

考虑到聊天室的特点,多并发、即时响应,因此执行速度要快;此外,聊天室没有复杂的业务逻辑和太高的技术难度,无需框架支持,因此轻量一些更容易部署、维护。

后端语言的选择

Go与C语言一样设计简洁,又具有Java、C#一样的面向对象特性,且轻量无需安装庞大的框架,此外Go同属编译型语言,底层友好,与Python、Nodejs、Ruby、PHP等解释型脚本语言相比,执行效率要高很多,同时其goroutine又天然支持并发,因此,除了容器化技术,go更适合web开发。

Go的缺点之一是缺少足够的框架支持,但其内置类库足够强大,并不特别依赖框架。(为了简化http请求、JWT还是采用了 gin框架)

// github地址 https://github.com/gin-gonic/gingo get github.com/gin-gonic/gin

Go得到google持续的开发支持,疫情并没有影响其更新速度,最近刚刚发布的最新版是Go1.15 Beta1 https://tip.golang.org/doc/go1.15

Go内置runtime,自带server,开箱即用,部署简单,甚至不需要Nginx

前端框架的选择

现在前端的开发要比后端琐碎复杂,因此不借助一个框架是很难的。在三大框架(React、Vue和Angular)中,Vue是最简洁高效的,在国内也有更好的生态支持。这里使用Vue-cli(内置webpack)

npm install -g @vue/cli  //yarn global add @vue/clivue create my-project

通讯组件

Web聊天室无疑需要用到WebSocket,这里使用了go的websocket实现

go get github.com/gorilla/websocket

Go 代码

——————

Gin框架是MVC结构,这里聊天信息的接收、广播操作主要通过,chatcontroller处理,包含4个文件:

hub.go :Hub维护了活动客户端,和广播客户端消息

package chatsockettype Hub struct {
    
      clients map[*Client]bool  broadcast chan []byte  register chan *Client  unregister chan *Client}func NewHub() *Hub {
    
      return &Hub{
    
        broadcast:  make(chan []byte),    register:   make(chan *Client),    unregister: make(chan *Client),    clients:    make(map[*Client]bool),  }}func (h *Hub) Run() {
    
      for {
    
        select {
    
        case client :=       h.clients[client] = true    case client :=       if _, ok := h.clients[client]; ok {
    
            delete(h.clients, client)        close(client.send)      }    case message :=       for client := range h.clients {
    
            select {
    
            case client.send         default:          close(client.send)          delete(h.clients, client)        }      }    }  }}

client.go :读取websocket消息,输入到hub;接收hub输出的消息,写入websocket

func (c *Client) readPump() {
    
      defer func() {
    
        c.hub.unregister     c.conn.Close()  }()  c.conn.SetReadLimit(maxMessageSize)  c.conn.SetReadDeadline(time.Now().Add(pongWait))  c.conn.SetPongHandler(func(string) error { c.conn.SetReadDeadline(time.Now().Add(pongWait)); return nil })  for {
    
        _, message, err := c.conn.ReadMessage()    if err != nil {
    
          if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
    
            log.Printf("error: %v", err)      }      break    }    message = bytes.TrimSpace(bytes.Replace(message, newline, space, -1))    // 加入自己的处理    message, _ = ProcessWSRequest(message)    c.hub.broadcast   }}func (c *Client) writePump() {
    
      ticker := time.NewTicker(pingPeriod)  defer func() {
    
        ticker.Stop()    c.conn.Close()  }()  for {
    
        select {
    
        case message, ok :=       c.conn.SetWriteDeadline(time.Now().Add(writeWait))      if !ok {
    
            // The hub closed the channel.        c.conn.WriteMessage(websocket.CloseMessage, []byte{})        return      }      w, err := c.conn.NextWriter(websocket.TextMessage)      if err != nil {
    
            return      }      w.Write(message)      // Add queued chat messages to the current websocket message.      n := len(c.send)      for i := 0; i < n; i++ {
    
            w.Write(newline)        w.Write(      }      if err := w.Close(); err != nil {
    
            return      }    case       c.conn.SetWriteDeadline(time.Now().Add(writeWait))      if err := c.conn.WriteMessage(websocket.PingMessage, nil); err != nil {
    
            return      }    }  }}func ServeWs(hub *Hub, w http.ResponseWriter, r *http.Request) {
    
      conn, err := upgrader.Upgrade(w, r, nil)  if err != nil {
    
        log.Println(err)    return  }  client := &Client{hub: hub, conn: conn, send: make(chan []byte, 256)}  client.hub.register   // Allow collection of memory referenced by the caller by doing all work in  // new goroutines.  go client.writePump()  go client.readPump()}func ProcessWSRequest(message []byte) ([]byte, error) {
    
      var msgGot MsgReceived  var respMesssage []byte  var err error  err = json.Unmarshal(message, &msgGot)  if err != nil {
    
        respMesssage = message    log.Printf("json.Unmarshal err: %v", err)  } else {
    
        msgGot.ChatTime = time.Now().Format("2006-01-02 15:04")    if msgGot.ChatType == "q" || msgGot.ChatType == "a" {
    
          var newid int      newid, err = InsertMessage(&msgGot)      if err == nil {
    
            msgGot.ID = newid      }    } else if msgGot.ChatType == "r"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值