实时聊天-go语言从入门到放弃 | 🏆 技术专题第二期征文

项目 例子已发布到 github 欢迎 Starvue

项目地址git

安装篇

windows

下载地址github

一路狂点 nextgolang

检查是否安装成功 命令行输入web

go version
 
复制代码

mac

方法一

brew install go
复制代码

方法二 比较快

下载vue-cli

安装json

验证vim

万能的 hello word

建立 hello.go 文件windows

package main

import "fmt"

func main() {
   fmt.Println("Hello, World!")
}
复制代码

运行跨域

go run hello.go
复制代码

运行

go build hello.go
./hello
复制代码

VsCode 扩展

镜像代理-Goproxy 中国

环境变量

vim ~/.zshrc 或者 vim .bash_profile

export GOROOT=/usr/local/go
# 项目目录
export GOPATH=~/go  
export PATH=${PATH}:$GOPATH/bin
复制代码

执行 source ~/.zshrc 或 source ~/.bash_profile 生效

检查命令

go env
复制代码

WebSocket

WebSocket 协议在2008年诞生,2011年成为国际标准。全部浏览器都已经支持了。

它的最大特色就是,服务器能够主动向客户端推送信息,客户端也能够主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。

github.com/gorilla/websocket

go的 websocket 库

获取方式

go get github.com/gorilla/websocket
复制代码

使用文档

进入主题

项目结构

  • realTimeChat
    • src
      • main.js
    • web
    • go.mod

src 为 go程序目录 web // vue-cli 构建的项目 go.mod 是 依赖包的管理(记录和解析对其余模块的依赖性)

生成方式 执行如下命令

cd RealTimeChat
go mod init src // init 后 跟 main.js所在的目录名称
复制代码

web 项目建立 请移动至

vue-cli 搭建项目之 项目建立和基本配置

主程序 main.go

package main

import (
	"encoding/json" // json格式化
	"fmt"
	"net/http" // http 服务

	"github.com/gorilla/websocket"
)

// map 映射,其键对应是一个指向 WebSocket 的指针,其值就是一个布尔值。咱们实际上并不须要这个值,但使用的映射数据结构须要有一个映射值,这样作更容易添加和删除单项。
var clients = make(map[*websocket.Conn]bool)

// 由客户端发送消息的队列
var broadcast = make(chan Message)

// Upgrader 用于升级 http 请求,把 http 请求升级为长链接的 WebSocket
var upgrader = websocket.Upgrader{
	// 解决跨域问题
	CheckOrigin: func(r *http.Request) bool {
		return true
	},
}

// 客户端惟一id
type userInfo struct {
	UserId string
	Code   string
}

// 用户信息+消息内容
type Message struct {
	Msg      string `json:"msg"`
	Username string `json:"username"`
}

// Upgrade 函数将 http 升级到 WebSocket 协议
func handler(w http.ResponseWriter, r *http.Request) {
	ws, err := upgrader.Upgrade(w, r, nil)
	// 获取id
	var info userInfo
	info.UserId = ws.RemoteAddr().String()
	info.Code = "auth"
	data, _ := json.Marshal(info)
	// 下发id
	ws.WriteMessage(websocket.TextMessage, []byte(string(data)))
	fmt.Println("用户:", ws.RemoteAddr().String(), "加入")
	if err != nil {
		fmt.Println(err)
		return
	}
	// 退出时关闭链接
	defer ws.Close()
	// 把新的客户端添加到全局的 "clients" 映射表中进行注册
	clients[ws] = true
	// 处理WebSocket的先消息
	for {
		var msg Message
		// 从链接中读取下一个JSON编码的消息,并将其存储在msg指向的值中。
		err := ws.ReadJSON(&msg)
		if err != nil {
			fmt.Println(err)
			delete(clients, ws)
			break
		}
		// 将新接收到的消息发送到广播频道
		broadcast <- msg
	}
}

// 广播消息
func handleMessages() {
	for {
		// 从“broadcast”中连续读取数据
		msg := <-broadcast
		// 经过各自的 WebSocket 链接将消息传播到全部客户端
		for client := range clients {
			fmt.Println('2')
			// WriteJSON将msg的JSON编码写为消息
			err := client.WriteJSON(&msg)
			if err != nil {
				fmt.Println(err)
				client.Close()
				delete(clients, client)
			}
		}
	}
}

func main() {

	// 打印输出信息。
	fmt.Println("ListenAndServe: 8000")

	// http 服务
	http.HandleFunc("/ws", handler)

	go handleMessages()

	err := http.ListenAndServe(":8000", nil)

	if err != nil {
		fmt.Println("ListenAndServe")
		fmt.Println(err)
	}
}
复制代码

src 目录下运行

go run main.go
复制代码

web vue主逻辑

...
mounted() {
    var self = this;
    this.ws = new WebSocket('ws://localhost:8000/ws');
    // 接收消息
    this.ws.addEventListener('message', function(e) {
        var res = JSON.parse(e.data);
        // 判断 是否为 下发惟一用户id
        if(res.Code === 'auth'){
          self.form.username = res.UserId.replace(RegExp('\\[::1]:', 'g'), '')
          self.upUSER_ID(self.form.username)
          return
        }
        // 消息类型,本身仍是别人,right 是本身
        var type = res.username == self.userid ? 'right' : 'left'
        // 存储消息 到 store
        self.addMessage(Object.assign({
          type: type
        },res))
    });
},
methods:{
    ...mapActions('user', ['upUSER_ID']),
    ...mapActions('message', ['addMessage']),
    // 发送消息
    submit() {
      this.ws.send(
        JSON.stringify({
          msg: this.form.msg,
          username: this.form.username
      }));
      this.form.msg = ''
    },  
}
...
复制代码

效果图

go run main.go
ListenAndServe: 8000
用户: [::1]:55023 加入
用户: [::1]:55055 加入
websocket: close 1001 (going away)
用户: [::1]:55062 加入
复制代码


未完待续,功能作的比较简易,以前设想的 注册登陆, 好友列表,聊天记录,发送私信 ,因时间有限 还没来得及实现,后续后继续完善

欢迎在评论区留言,能够的话

🏆 技术专题第二期 | 我与 Go 的那些事......

相关文章
相关标签/搜索