好的,下面是一个使用 go-zero
框架实现 WebSocket 咨询问答服务的完整示例,包括高并发处理、使用 sync.Map
代替普通的 map
、细条检测以及基本的测试用例。虽然您提到不需要身份验证,但我们会在代码中留下一些相关的框架,以便将来扩展。
步骤 1: 创建基本项目结构
首先确保你的 Go 环境已安装了 go-zero。
go get -u github.com/zeromicro/go-zero
创建一个新的 Go 项目:
mkdir websocket-service
cd websocket-service
go mod init websocket-service
步骤 2: 定义 API 文件
创建 API 文件 api/websocket.api
:
type WebSocketRequest {
userId int64 `json:"user_id"`
message string `json:"message"`
}
type WebSocketResponse {
status string `json:"status"`
response string `json:"response"`
}
service websocket-api {
@server(
path="/ws",
method="GET"
)
webSocket ws(WebSocketRequest) returns (WebSocketResponse)
}
生成代码:
goctl api go -api api/websocket.api -dir .
步骤 3: 实现 WebSocket 处理逻辑
在生成的 handler 文件中(通常是 handler/ws_handler.go
),添加 WebSocket 的处理逻辑:
package handler
import (
"net/http"
"strconv"
"sync"
"github.com/gorilla/websocket"
)
var upgrader = websocket.Upgrader{}
var connections sync.Map // 用于存储连接
// WsHandler handles the WebSocket connection.
func WsHandler(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
http.Error(w, "Could not upgrade connection", http.StatusInternalServerError)
return
}
defer conn.Close()
userID := r.URL.Query().Get("user_id")
connections.Store(userID, conn)
for {
var req WebSocketRequest
err := conn.ReadJSON(&req)
if err != nil {
break // 客户端关闭连接或发生错误
}
response := handleMessage(req)
err = conn.WriteJSON(response)
if err != nil {
break // 写入失败,可能是连接问题
}
}
}
// handleMessage handles incoming messages and generates responses.
func handleMessage(req WebSocketRequest) WebSocketResponse {
if len(req.Message) > 200 { // 假设最大消息长度为200字符
return WebSocketResponse{
Status: "error",
Response: "Message is too long.",
}
}
return WebSocketResponse{
Status: "success",
Response: "Received message from user " + strconv.FormatInt(req.UserId, 10) + ": " + req.Message,
}
}
步骤 4: 启动服务器
创建文件 main.go
:
package main
import (
"net/http"
"github.com/gorilla/mux"
"./handler" // 导入自定义 handler 包,你可能需要调整路径。
)
func main() {
r := mux.NewRouter()
r.HandleFunc("/ws", handler.WsHandler).Methods(http.MethodGet)
http.ListenAndServe(":8080", r)
}
步骤 5: 添加测试用例
创建文件夹 tests
并在其中添加测试文件,例如:tests/ws_handler_test.go
:
package tests
import (
"bytes"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"./handler" // 根据实际路径调整引入的模块路径。
)
func TestWsHandler(t *testing.T) {
reqBody := handler.WebSocketRequest{
UserId: 1,
Message: "Hello World",
}
body, _ := json.Marshal(reqBody)
req := httptest.NewRequest(http.MethodGet, "/ws?user_id=1", bytes.NewBuffer(body))
respRecorder := httptest.NewRecorder()
handler.WsHandler(respRecorder, req)
resp := respRecorder.Result()
if resp.StatusCode != http.StatusSwitchingProtocols {
t.Errorf("expected status %v; got %v", http.StatusSwitchingProtocols, resp.StatusCode)
}
}
完整代码示例结构
- main.go : 启动 HTTP 服务
- api/websocket.api : 定义 API
- handler/ws_handler.go : 实现 WebSocket 处理
- tests/ws_handler_test.go : 测试用例
如何运行服务和测试用例
- 确保你已经安装了相关依赖项。
- 在项目根目录下运行以下命令以启动服务器:
go run main.go handler/ws_handler.go
- 使用工具(如 Postman 或浏览器)连接到
/ws
路径进行测试。可以通过 JavaScript 创建一个简单的前端来与这个接口交互。 - 为了运行测试用例,在终端中执行以下命令:
go test ./tests/...
这是一个完整且可运行的基础框架,你可以根据需要扩展更复杂的功能。如果有其他具体需求,请随时告诉我!
内容由零声教学AI助手提供,问题来源于学员提问