在本文中,您将使用 Websockets 在 Golang 中构建一个实时聊天应用程序。您还将使用 Docker 将应用程序容器化。
实时通信可能很难在您的应用程序中实现,但并非必须如此。Websockets 提供了一种简单而紧凑的方法,几乎可以在任何编程语言中使用。
在本文中,您将使用 Websockets 在 Golang 中构建一个实时聊天应用程序。您还将使用 Docker 将应用程序容器化。
构建实时聊天先决条件
- Golang安装
- 体验基本的 Go 语法
- Docker 安装(可选)
设置我们的 Go 项目
让我们从创建项目所需的文件开始。这可以使用以下命令完成:
mkdir public
touch main.go Dockerfile public/index.html public/styles.css public/main.js
注意:mkdir命令创建一个新目录,touch 命令用于创建新文件。
基本 HTTP 服务器
并不是说您已经完成了文件夹结构的设置,您将继续使用gin包实现一个基本的 HTTP 服务器。
为此,您首先需要安装所需的依赖项:
go get github.com/gin-gonic/gin
go get gopkg.in/olahol/melody.v1
服务器将有一个 GET 端点来处理所有 Websocket 请求,并且还将提供一个用作前端的静态目录。
package main
import (
static "github.com/gin-contrib/static"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.Use(static.Serve("/", static.LocalFile("./public", true)))
r.GET("/ws", func(c *gin.Context) {
m.HandleRequest(c.Writer, c.Request)
})
r.Run(":5000")
}
如您所见,服务器静态地为您之前创建的公共目录提供服务,并公开 /ws 的单个 GET 端点。
然后使用 run 命令启动服务器,该命令将端口作为参数。
实施 Websockets 服务器
现在您已经有了一个可以构建的基本 HTTP 服务器,让我们继续实现 Websockets 功能。为此,您将使用Melody 库,这是一个用于 Golang 编程语言的简约 Websockets 框架。
由于您只有一个 Websocket 事件,每当您发送聊天消息时都会触发该事件,因此您只需要将消息广播给其他客户端即可。
package main
import (
static "github.com/gin-contrib/static"
"github.com/gin-gonic/gin"
"gopkg.in/olahol/melody.v1"
)
func main() {
r := gin.Default()
m := melody.New()
r.Use(static.Serve("/", static.LocalFile("./public", true)))
r.GET("/ws", func(c *gin.Context) {
m.HandleRequest(c.Writer, c.Request)
})
m.HandleMessage(func(s *melody.Session, msg []byte) {
m.Broadcast(msg)
})
r.Run(":5000")
}
HandleMessage() 函数用于接收发送到 Websockets GET 端点的所有消息。之后,您将消息广播给所有连接的客户端。
添加前端
下一步是在 index.html 文件中创建基本布局。布局包含用户名的输入字段和消息的文本区域。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
<title>Websockets Chat</title>
<link rel="stylesheet" href="styles.css">
<script type="text/javascript" src="https://cdn.socket.io/socket.io-1.4.5.js"></script>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6 offset-md-3 col-sm-12">
<h1 class="text-center">Socket IO Chat</h1>
<br>
<div id="status"></div>
<div id="chat">
<input type="text" name="username" id="username" class="form-control" placeholder="Enter name...">
<br>
<div class="card">
<div id="messages" class="card-block"></div>
</div>
<br>
<textarea id="textarea" name="inputMessage" class="form-control" placeholder="Enter message..."></textarea>
<br>
<button id="send" class="btn">Send</button>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="main.js"></script>
</body>
</html>
您还在底部包含了 main.js 文件,这样您就可以为前端实现 websockets 客户端功能。
首先,您需要使用 document.querySelector() 函数从 Javascript DOM 获取前端布局的元素。
const input = document.querySelector('#textarea')
const messages = document.querySelector('#messages')
const username = document.querySelector('#username')
const send = document.querySelector('#send')
接下来,您连接到 Websockets 服务器并为onmessage事件创建侦听器。该事件将触发一个功能,将您收到的新消息插入到聊天中。
const url = "ws://" + window.location.host + "/ws";
const ws = new WebSocket(url);
ws.onmessage = function (msg) {
insertMessage(JSON.parse(msg.data))
};
现在您可以接收传入的消息,是时候通过在发送按钮上放置一个onclick事件来发送消息了。
send.onclick = () => {
const message = {
username: username.value,
content: input.value,
}
ws.send(JSON.stringify(message));
input.value = "";
};
下一步是实现 insertMessage() 函数,该函数将使用 Javascript DOM 将接收到的消息插入文本区域。
/**
* Insert a message into the UI
* @param {Message that will be displayed in the UI} messageObj
*/
function insertMessage(messageObj) {
// Create a div object which will hold the message
const message = document.createElement('div')
// Set the attribute of the message div
message.setAttribute('class', 'chat-message')
console.log("name: " +messageObj.username + " content: " + messageObj.content)
message.textContent = `${messageObj.username}: ${messageObj.content}`
// Append the message to our chat div
messages.appendChild(message)
// Insert the message as the first message of our chat
messages.insertBefore(message, messages.firstChild)
}
所有这些都会产生以下 main.js 文件:
const input = document.querySelector('#textarea')
const messages = document.querySelector('#messages')
const username = document.querySelector('#username')
const send = document.querySelector('#send')
const url = "ws://" + window.location.host + "/ws";
const ws = new WebSocket(url);
ws.onmessage = function (msg) {
insertMessage(JSON.parse(msg.data))
};
send.onclick = () => {
const message = {
username: username.value,
content: input.value,
}
ws.send(JSON.stringify(message));
input.value = "";
};
/**
* Insert a message into the UI
* @param {Message that will be displayed in the UI} messageObj
*/
function insertMessage(messageObj) {
// Create a div object which will hold the message
const message = document.createElement('div')
// Set the attribute of the message div
message.setAttribute('class', 'chat-message')
console.log("name: " +messageObj.username + " content: " + messageObj.content)
message.textContent = `${messageObj.username}: ${messageObj.content}`
// Append the message to our chat div
messages.appendChild(message)
// Insert the message as the first message of our chat
messages.insertBefore(message, messages.firstChild)
}
最后,您将向 styles.css 文件添加一些 css。
#messages{
height:300px;
overflow-y: scroll;
}
测试应用程序
太棒了,现在我们已经完成了应用程序,您可以使用以下命令运行它。
go run main.go
您现在可以在两个不同的浏览器选项卡中访问 localhost:5000 并开始相互聊天。
容器化应用程序
现在的最后一步是使用 Docker 将应用程序容器化。为此,我们可以使用一个简单的 Dockerfile 来构建和运行应用程序。
FROM golang:latest
# Set the Current Working Directory inside the container
WORKDIR /app
RUN GO111MODULE=on
# Copy go mod and sum files
COPY go.mod go.sum ./
# Download all dependencies. Dependencies will be cached if the go.mod and go.sum files are not changed
RUN go mod download
COPY . .
# Build the application
RUN go build -o main .
# Expose port 5000 to the outside world
EXPOSE 5000
# Command to run the executable
CMD ["./main"]
可以使用build命令构建图像。-t 标志用于为图像提供自定义标签。
docker build -t websocketschat .
您现在可以使用运行命令运行图像。-p 标志用于设置应向主机公开的端口。
docker run -p 5000:5000 websocketschat
整个项目和许多其他 Golang 项目都可以在我的 Github上找到。
结论
你一路走到最后!我希望本文能帮助您了解 Websockets 以及如何在 Golang 应用程序中使用它。
作者:Gabriel Tanner
原文链接:https://gabrieltanner.org/blog/realtime-chat-go-websockets/
本文来自作者投稿,版权归原作者所有。如需转载,请注明出处:https://www.nxrte.com/jishu/im/14802.html