Building and Testing WebSocket Services in Go: A Hands‑On Guide
This article walks through developing a simple Go WebSocket server that echoes the current time, shows a minimal client, compares startup speed with Java, and provides full source code and test logs for practical performance testing.
After mastering HTTP basics, the author dives into the WebSocket protocol, revisits earlier Java and Python socket tests, and presents a hands‑on Go implementation for both server and client, including performance observations.
Dependencies
The implementation relies on Go's standard /net/websocket package and the widely used /gorilla/websocket library, which can serve both as a server endpoint and a client requester.
WebSocket Server
Many online tutorials are outdated; the /net/websocket package is rarely demonstrated for server‑side use, leading to confusion for beginners. The server logic is straightforward: upon receiving a message, it replies with the current timestamp.
// Echo
// @Description: WebSocket handler
func Echo(ws *websocket.Conn) {
var err error
for {
var reply string
if err = websocket.Message.Receive(ws, &reply); err != nil {
fmt.Println("receive failed:", err)
break
}
log.Printf("Received message: %s", reply)
msg := string(time.Now().String())
websocket.Message.Send(ws, msg)
}
}
// TestSer
// @Description: create a WebSocket endpoint
func TestSer(t *testing.T) {
// Register WebSocket route
http.HandleFunc("/websocket", func(w http.ResponseWriter, req *http.Request) {
s := websocket.Server{Handler: websocket.Handler(Echo)}
s.ServeHTTP(w, req)
})
if err := http.ListenAndServe(":1234", nil); err != nil {
log.Fatal("ListenAndServe:", err)
}
}The key difficulty is converting a WebSocket handler into an HTTP handler, effectively performing the "upgrader" step.
Client
The client simply connects, sends a greeting, and prints the server's timestamp. For more extensive testing, the author suggests using Go channels to coordinate reads and writes.
// TestWebSocket
// @Description: test WebSocket script
func TestWebSocket(t *testing.T) {
url := "wss://.ltd:8443/ws/v5/public"
c, res, err := websocket.DefaultDialer.Dial(url, nil)
if err != nil {
log.Fatal("Connection failed:", err)
}
log.Printf("Response: %s", fmt.Sprint(res))
defer c.Close()
done := make(chan struct{})
err = c.WriteMessage(websocket.TextMessage, []byte("你好,我是FunTester"))
if err != nil {
fmt.Println(err)
}
go func() {
defer close(done)
for {
_, message, err := c.ReadMessage()
if err != nil {
log.Fatal(err)
break
}
log.Printf("Received message: %s", message)
}
}()
<-done
}Testing
Start the server first, then run the client. The Go implementation starts noticeably faster than the comparable Java version, highlighting Go's rapid startup advantage.
A Java test client using the FunTester framework is also provided for side‑by‑side comparison.
package com.funtest.javatest;
import com.funtester.frame.SourceCode;
import com.funtester.socket.WebSocketFunClient;
public class WebSocketT extends SourceCode {
public static void main(String[] args) {
WebSocketFunClient instance = WebSocketFunClient.getInstance("ws://localhost:1234/websocket");
instance.connect();
instance.send("你好,我是FunTester - Java ,Have Fun ~ Tester !");
}
}Sample logs show the server receiving messages from both Go and Java clients and printing the echoed timestamps.
=== RUN TestSer
2021/11/09 18:03:20 收到消息:你好,我是FunTester - Go ,Have Fun ~ Tester !
2021/11/09 18:05:49 收到消息:你好,我是FunTester - Java ,Have Fun ~ Tester !Overall, the Go WebSocket example demonstrates concise code, quick startup, and easy testing, making it a practical reference for developers building real‑time services.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
