Baike.dev
All toolsAI codingTrendingOpen sourceNewsSubmit
Log in
< Back to tools
G

go-chat

> 编程语言
Open source

go-chat.使用Go基于WebSocket开发的web聊天应用。单聊,群聊。文字,图片,语音,视频消息,屏幕共享,剪切板图片,基于WebRTC的P2P语音通话,视频聊天。

1.1K stars0 likes0 views
WebsiteGitHub

About

go-chat.使用Go基于WebSocket开发的web聊天应用。单聊,群聊。文字,图片,语音,视频消息,屏幕共享,剪切板图片,基于WebRTC的P2P语音通话,视频聊天。

go-chat

使用Go基于WebSocket的通讯聊天软件。

功能列表

  • 登录注册
  • 修改头像
  • 群聊天
  • 群好友列表
  • 单人聊天
  • 添加好友
  • 添加群组
  • 文本消息
  • 剪切板图片
  • 图片消息
  • 文件发送
  • 语音消息
  • 视频消息
  • 屏幕共享(基于图片)
  • 视频通话(基于WebRTC的p2p视频通话)
  • 分布式部署(通过kafka全局消息队列,统一消息传递,可以水平扩展系统)

后端

代码仓库 go中协程是非常轻量级的。在每个client接入的时候,为每一个client开启一个协程,能够在单机实现更大的并发。同时go的channel,可以非常完美的解耦client接入和消息的转发等操作。

通过go-chat,可以掌握channel的和Select的配合使用,ORM框架的使用,web框架Gin的使用,配置管理,日志操作,还包括proto buffer协议的使用,等一些列项目中常用的技术。

后端技术和框架

  • web框架Gin
  • 长连接WebSocket
  • 日志框架Uber的zap
  • 配置管理viper
  • ORM框架gorm
  • 通讯协议Google的proto buffer
  • makefile 的编写
  • 数据库MySQL
  • 图片文件二进制操作

前端

基于react,UI和基本组件是使用ant design。可以很方便搭建前端界面。

界面选择单页框架可以更加方便写聊天界面,比如像消息提醒,可以在一个界面接受到消息进行提醒,不会因为换页面或者查看其他内容影响消息接受。 前端代码仓库:

前端技术和框架

  • React
  • Redux状态管理
  • AntDesign
  • proto buffer的使用
  • WebSocket
  • 剪切板的文件读取和操作
  • 聊天框发送文字显示底部
  • FileReader对文件操作
  • ArrayBuffer,Blob,Uint8Array之间的转换
  • 获取摄像头视频(mediaDevices)
  • 获取麦克风音频(Recorder)
  • 获取屏幕共享(mediaDevices)
  • WebRTC的p2p视频通话

截图

  • 语音,文字,图片,视频消息

  • 视频通话

  • 屏幕共享

消息协议

protocol buffer协议

…

选择协议原因

通过消息体能看出,消息大部分都是字符串或者整型类型。通过json就可以进行传输。那为什么要选择google的protocol buffer进行传输呢?

  1. 传输快 因为protobuf序列化后的大小是json的10分之一,是xml格式的20分之一,但是性能却是它们的5~100倍.
  2. 支持二进制 当我们看到消息体最后一个字段,是定义的bytes,二进制类型。 我们在传输图片,文件,视频等内容的时候,可以将文件直接通过socket消息进行传输。 当然我们也可以将文件先通过http接口上传后,然后返回路径,再通过socket消息进行传输。但是这样只能实现固定大小文件的传输,如果我们是语音电话,或者视频电话的时候,就不能传输流。

快速运行

MySQL创建数据库

CREATE DATABASE go-chat;

创建表

将go-chat.sql里面的sql语句复制到控制台创建对应的表。

在user表里面添加初始化用户

手动添加用户或者通过前端进行注册用户。
初始用户名:user001,密码:user001
初始用户名:user002,密码:user002

运行go程序

go环境的基本配置 ...

拉取后端代码

git clone https://github.com/kone-net/go-chat

进入目录

cd go-chat

拉取程序所需依赖

go mod download

修改数据库配置文件

修改数据库连接用户名,密码等信息。

vim config.toml

[mysql]
host = "127.0.0.1"
name = "go-chat"
password = "root1234"
port = 3306
table_prefix = ""
user = "root"

运行程序

go run cmd/main.go

运行前端代码

前端代码仓库:


分布式部署

  • 拉取代码 将代码拉取到服务器,运行make build构建后端代码。
  • 构建后端服务镜像 进入目录deployments/docker 通过目录下的Dockerfile构建镜像
docker build -t konenet/gochat:1.0 .
  • 部署服务 需要部署nginx进行反向代理,mysql保存数据,1个或者多个后端服务。
  • 在config.toml中配置分布式消息队列 将msgChannelType中的channelType修改为kafka,就为分布式消息队列。需要填写消息队列对应的地址和topic
appName = "chat_room"

[mysql]
host = "mysql8"
name = "go-chat-message"
password = "thepswdforroot"
port = 3306
tablePrefix = ""
user = "root"

[log]
level = "debug"
path = "logs/chat.log"

[staticPath]
filePath = "web/static/file/"

[msgChannelType]
channelType = "kafka"

kafkaHosts = "kafka:9092"
kafkaTopic = "go-chat-message"
  • 启动服务 通过deployments/docker下的docker-compose.yml进行启动。
docker-compose up -d
  • 注意:分布式部署后,上传的文件视频等,可能会因为负载到不同的机器上,导致文件找不到的情况,所以需要一个在线或者分布式文件服务器。

代码结构

…

Makefile

程序打包

在根目录下执行make命令 mac

make build-darwin

实际执行命令是Makefile下的
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o bin/chat cmd/main.go

linux

make build

实际执行命令是Makefile下的
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o bin/chat cmd/main.go

后端proto文件生成

如果修改了message.proto,就需要重新编译生成对应的go文件。 在根目录下执行

make proto

实际执行命令是Makefile下的
protoc --gogo_out=. protocol/*.proto
# https://github.com/protocolbuffers/protobuf-javascript/releases/tag/v4.0.0
# https://github.com/protocolbuffers/protobuf/releases

如果本地没有安装proto文件,需要先进行安装,不然找不到protoc命令。 使用gogoprotobuf

安装protobuf库文件

go get github.com/golang/protobuf/proto

安装protoc-gen-go

go install google.golang.org/protobuf/cmd/protoc-gen-go@latest

在根目录测试:

protoc --go_out=. pkg/protocol/*.proto

代码说明

WebSocket

该文件是gin的路由映射,将普通的get请求,Upgrader为socket连接

// router/router.go
func NewRouter() *gin.Engine {
 gin.SetMode(gin.ReleaseMode)

 server := gin.Default()
 server.Use(Cors())
 server.Use(Recovery)

 socket := RunSocekt

 group := server.Group("")
 {
        ...

  group.GET("/socket.io", socket)
 }
 return server
}

这部分对请求进行升级为WebSocket。

  • c.Query("user")用户登录后,会获取用户的uuid,在连接到socket时会携带用户的uuid。
  • 通过该uuid和connection进行关联。
  • server.MyServer.Register { document.getElementById("messageArea").addEventListener("paste", (e) => { var data = e.clipboardData if (!data.items) { return; } var items = data.items if (null == items || items.length { let imgData = e.target.result // 上传文件必须将ArrayBuffer转换为Uint8Array let data = { fromUsername: localStorage.username, from: this.state.fromUser, to: this.state.toUser, messageType: this.state.messageType, content: this.state.value, contentType: 3, file: new Uint8Array(imgData) } let message = protobuf.lookup("protocol.Message") const messagePB = message.create(data) socket.send(message.encode(messagePB).finish()) this.appendImgToPanel(imgData) }) }, false) }

### 上传录制的视频

上传语音同原理

* 获取视频调用权限。
* 通过mediaDevices获取视频流,或者音频流,或者屏幕分享的视频流。
* this.recorder.start(1000)设定每秒返回一段流。
* 通过MediaRecorder将流转换为二进制,存入dataChunks数组中。
* 松开按钮后,将dataChunks中的数据合成一段二进制。
* 通过FileReader,将blob转换为ArrayBuffer格式。
* 将ArrayBuffer内容转换为Uint8Array二进制,放在消息体。
* 通过protobuf将消息转换成对应协议。
* 通过socket进行传输。
* 最后,将本地的视频,音频追加到聊天框里面。

**特别注意: 获取视频,音频,屏幕分享调用权限,必须是https协议或者是localhost,127.0.0.1 本地IP地址,所有本地测试可以开启几个浏览器,或者分别用这两个本地IP进行2tab测试**

```javascript
/**
     * 当按下按钮时录制视频
     */
    dataChunks = [];
    recorder = null;
    startVideoRecord = (e) => {
        navigator.getUserMedia = navigator.getUserMedia ||
            navigator.webkitGetUserMedia ||
            navigator.mozGetUserMedia ||
            navigator.msGetUserMedia; //获取媒体对象(这里指摄像头)

        let preview = document.getElementById("preview");
        this.setState({
            isRecord: true
        })

        navigator.mediaDevices
            .getUserMedia({
                audio: true,
                video: true,
            }).then((stream) => {
                preview.srcObject = stream;
                this.recorder = new MediaRecorder(stream);

                this.recorder.ondataavailable = (event) => {
                    let data = event.data;
                    this.dataChunks.push(data);
                };
                this.recorder.start(1000);
            });
    }

    /**
     * 松开按钮发送视频到服务器
     * @param {事件} e 
     */
    stopVideoRecord = (e) => {
        this.setState({
            isRecord: false
        })

        let recordedBlob = new Blob(this.dataChunks, { type: "video/webm" });

        let reader = new FileReader()
        reader.readAsArrayBuffer(recordedBlob)

        reader.onload = ((e) => {
            let fileData = e.target.result

            // 上传文件必须将ArrayBuffer转换为Uint8Array
            let data = {
                fromUsername: localStorage.username,
                from: this.state.fromUser,
                to: this.state.toUser,
                messageType: this.state.messageType,
                content: this.state.value,
                contentType: 3,
                file: new Uint8Array(fileData)
            }
            let message = protobuf.lookup("protocol.Message")
            const messagePB = message.create(data)
            socket.send(message.encode(messagePB).finish())
        })

        this.setState({
            comments: [
                ...this.state.comments,
                {
                    author: localStorage.username,
                    avatar: this.state.user.avatar,
                    content: 

,
                    datetime: moment().fromNow(),
                },
            ],
        }, () => {
            this.scrollToBottom()
        })
        if (this.recorder) {
            this.recorder.stop()
            this.recorder = null
        }
        let preview = document.getElementById("preview");
        preview.srcObject.getTracks().forEach((track) => track.stop());
        this.dataChunks = []
    }

Issues· 0 open

View all issuesOpen on GitHub

No open issues yet, or sync has not completed.

> Tags

Gochatchat-applicationgogolang

No comments yet. Be the first to share.

> Details

PublishedAug 1, 2026
UpdatedSep 17, 2026
Category编程语言
PricingOpen source

> Related tools

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言