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



技术选型
——————
考虑到聊天室的特点,多并发、即时响应,因此执行速度要快;此外,聊天室没有复杂的业务逻辑和太高的技术难度,无需框架支持,因此轻量一些更容易部署、维护。
后端语言的选择
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"
Golang+Vue实现Web聊天室:轻量级框架选择与实现

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

被折叠的 条评论
为什么被折叠?



