go - 在 golang 中一对一聊天

标签 go websocket socket.io chat

我想在 Revel 框架中创建一对一聊天,但出现错误。最初按照demo在revel chat中工作,但是刷新页面不起作用,所以我尝试了这种方法,但不知道如何处理单个聊天。

这是一个错误:

app server.go:2848: http: panic serving 127.0.0.1:50420: interface conversion: interface is nil, not io.Writer goroutine 166 [running]: net/http.(*conn).serve.func1(0xc4201d03c0)

我的 go 代码是我处理 ws root 的地方,单用户聊天需要数据库连接。我正在为此使用 posgres

package main

import (
    "log"
    "net/http"

    "github.com/gorilla/websocket"
)

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

// Configure the upgrader
var upgrader = websocket.Upgrader{
    CheckOrigin: func(r *http.Request) bool {
        return true
    },
}

// Define our message object
type Message struct {
    Email    string `json:"email"`
    Username string `json:"username"`
    Message  string `json:"message"`
    Created  string `json:"created"`
}

func main() {
    // Create a simple file server
    fs := http.FileServer(http.Dir("public"))
    http.Handle("/", fs)

    // Configure websocket route
    http.HandleFunc("/ws", handleConnections)

    // Start listening for incoming chat messages
    go handleMessages()

    // Start the server on localhost port 8000 and log any errors
    log.Println("http server started on :8090")
    err := http.ListenAndServe(":8090", nil)
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}

func handleConnections(w http.ResponseWriter, r *http.Request) {
    // Upgrade initial GET request to a websocket
    ws, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Fatal(err)
    }
    // Make sure we close the connection when the function returns
    defer ws.Close()

    // Register our new client
    clients[ws] = true

    for {
        var msg Message
        // Read in a new message as JSON and map it to a Message object
        err := ws.ReadJSON(&msg)
        if err != nil {
            log.Printf("error: %v", err)
            delete(clients, ws)
            break
        }
        // Send the newly received message to the broadcast channel
        broadcast <- msg
    }
}

func handleMessages() {
    for {
        // Grab the next message from the broadcast channel
        msg := <-broadcast
        // Send it out to every client that is currently connected
        for client := range clients {
            err := client.WriteJSON(msg)
            if err != nil {
                log.Printf("error: %v", err)
                client.Close()
                delete(clients, client)
            }
        }
    }
}

最佳答案

我认为您错误地使用了 gorilla/websocket API。您复制了 echo 示例,它是一个基本演示,预计只能处理单个 ws 连接。从 chat 示例开始。特别要注意 serveWs 是一个非阻塞调用,而您的 handleConnections 是阻塞的,即它永远不会返回。在此处查看 gorilla/websocket API 使用的完整示例: https://github.com/tinode/chat/blob/master/server/wshandler.go

正如 Cerise L 正确指出的那样,您的 clients 肯定有一场比赛,尽管我认为这不太可能产生 panic 。我认为最可能的 panic 来源是在关闭的 http 连接上调用 Upgrade。不可能准确地说,因为您没有发布 panic 的完整输出。

关于go - 在 golang 中一对一聊天,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47280162/

相关文章:

go - 来自 Opencensus Libraries for Golang 的 vendor 问题

go - 使用缓冲区的 csv 编写器导致输出为空

node.js - 如何使用 nestjs 和 socket.io 创建房间

templates - 样式表不适用于使用 chi 路由器的 go html 模板

templates - 如何将变量传递给模板并在 beego 中接收变量

python - 如何使用 django channel 和 websockets 从服务器的任何地方向客户端发送事件

ssl - WebSockets 和 HTTPS 负载平衡器

python - 从 WebSocket 提取数据的最快方法

javascript - 带有 Angular 的 socket.io 不会立即显示消息

node.js - 缺少socket.io.js