實時聊天-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 的那些事......

相關文章
相關標籤/搜索