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 上,并处理客户端连接和消息处理。客户端连接到服务器并定期发送消息。服务器接收消息并将其广播给所有已连接的客户端。

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

相关推荐
xcLeigh2 小时前
Go入门:变量声明的五种方式详解
java·开发语言·golang
techdashen10 小时前
Go设计取舍之三: 0.3ns每次的错误Benchmark
开发语言·后端·golang
techdashen11 小时前
Go设计取舍之四: map不变时能否并发修改不同value
开发语言·后端·golang
名字还没想好☜12 小时前
Go 表驱动测试实战:用 t.Run 子测试组织可维护的单元测试
golang·单元测试·log4j·go·testing
golang学习记13 小时前
Claude Code写哪种变成语言最快?
golang·claude code
ShuiShenHuoLe13 小时前
Go html/template 使用入门
开发语言·golang·html
Achou.Wang1 天前
深入理解go语言-第5章 并发编程——Go的灵魂
大数据·算法·golang
名字还没想好☜1 天前
Go 的 time.After 在 select 循环里内存泄漏:定时器堆积原理与 timer.Reset 正确姿势
java·数据库·golang·go·goroutine
ttwuai1 天前
GoFrame 后台日志清空失败:无 WHERE 删除为什么被拦住
前端·golang
进击的程序猿~1 天前
Go 并发底层原理面试学习指南
开发语言·面试·golang