Golang 中实现实时聊天通讯

客户端代码

go 复制代码
package main

import (
    "fmt"
    "log"
    "net/url"
    "os"
    "os/signal"
    "time"

    "github.com/gorilla/websocket"
)

func main() {
    interrupt := make(chan os.Signal, 1)
    signal.Notify(interrupt, os.Interrupt)

    u := url.URL{Scheme: "ws", Host: "localhost:8080", Path: "/chat"}
    log.Printf("connecting to %s", u.String())

    c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
    if err != nil {
        log.Fatal("dial:", err)
    }
    defer c.Close()

    done := make(chan struct{})

    go func() {
        defer close(done)
        for {
            _, message, err := c.ReadMessage()
            if err != nil {
                log.Println("read:", err)
                return
            }
            log.Printf("received: %s", message)
        }
    }()

    ticker := time.NewTicker(time.Second)
    defer ticker.Stop()

    for {
        select {
        case <-done:
            return
        case t := <-ticker.C:
            err := c.WriteMessage(websocket.TextMessage, []byte(t.String()))
            if err != nil {
                log.Println("write:", err)
                return
            }
        case <-interrupt:
            log.Println("interrupt")
            err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
            if err != nil {
                log.Println("write close:", err)
                return
            }
            select {
            case <-done:
            case <-time.After(time.Second):
            }
            return
        }
    }
}

服务器端代码

go 复制代码
package main

import (
    "log"
    "net/http"

    "github.com/gorilla/websocket"
)

var clients = make(map[*websocket.Conn]bool) 
var broadcast = make(chan Message)            

type Message struct {
    Username string `json:"username"`
    Message  string `json:"message"`
}

func main() {
    http.HandleFunc("/chat", handleConnections)
    go handleMessages()
    log.Println("Server started on localhost:8080")
    err := http.ListenAndServe(":8080", nil)
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}

func handleConnections(w http.ResponseWriter, r *http.Request) {
    upgrader := websocket.Upgrader{}
    ws, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Fatal(err)
    }
    defer ws.Close()

    clients[ws] = true

    for {
        var msg Message
        err := ws.ReadJSON(&msg)
        if err != nil {
            log.Printf(": %v", err)
            delete(clients, ws)
            break
        }
        broadcast <- msg
    }
}

func handleMessages() {
    for {
        msg := <-broadcast
        for client := range clients {
            err := client.WriteJSON(msg)
            if err != nil {
                log.Printf(": %v", err)
                client.Close()
                delete(clients, client)
            }
        }
    }
}

以上代码创建了一个简单的聊天服务器和一个聊天客户端,通过 WebSocket 进行实时通信。服务器监听在 localhost:8080 上,并处理客户端连接和消息处理。客户端连接到服务器并定期发送消息。服务器接收消息并将其广播给所有已连接的客户端。

可以根据具体需求进行更多的定制和扩展。

相关推荐
人邮异步社区5 小时前
推荐几本学习计算机语言的书
java·c语言·c++·python·学习·golang
千码君201612 小时前
Go语言:解决 “package xxx is not in std”的思路
开发语言·后端·golang
Ypuyu12 小时前
【GoLang】【框架学习】【GORM】4. 使用 BeforeUpdate hook 操作时,出现反射报错
开发语言·学习·golang
脚踏实地的大梦想家13 小时前
【Go】P17 Go语言并发编程核心:深入理解 Goroutine (从入门到实战)
java·开发语言·golang
洲覆21 小时前
go-mysql-transfer 伪装从库实现 MySQL 到 Redis 数据同步(完整配置)
数据库·redis·mysql·golang
无知就要求知1 天前
golang封装可扩展的crontab
开发语言·后端·golang
雨中散步撒哈拉1 天前
14、做中学 | 初二上期 Golang集合Map
开发语言·后端·golang
paopaokaka_luck1 天前
基于SpringBoot+Vue的助农扶贫平台(AI问答、WebSocket实时聊天、快递物流API、协同过滤算法、Echarts图形化分析、分享链接到微博)
java·vue.js·spring boot·后端·websocket·spring
Yeats_Liao2 天前
Go Web 编程快速入门 13 - 部署与运维:Docker容器化、Kubernetes编排与CI/CD
运维·前端·后端·golang
Yeats_Liao2 天前
Go Web 编程快速入门 14 - 性能优化与最佳实践:Go应用性能分析、内存管理、并发编程最佳实践
前端·后端·性能优化·golang