Go-WS is a wrapper built around Gorilla WebSocket, designed to simplify and accelerate WebSocket communication for both server and client implementations in Go.
It introduces high-level event emitters, request-response abstractions, and message parsing logic, making it ideal for building scalable real-time applications.
- Easy WebSocket server and client setup
- Event-driven architecture (connection, disconnection, errors, messages)
- Request-response pattern built-in
- Custom message parsing and typed handler registration
- Graceful connection handling with ID assignment
- Thread-safe message sending
- TLS certificate support (generate/load/save)
- Reconnectable clients
go get github.com/GTedZ/gows
server := gows.NewServer("0.0.0.0", "/ws")
err := server.ListenAndServe(3000)
if err != nil {
fmt.Println("ListenAndServe error", err.Error())
}
server.SetCheckOrigin(
func(r *http.Request) bool {
return true // Allow all origins
},
)
server.SetCheckOrigin(nil)
server.OnConnect = func(conn *gows.Connection) {
fmt.Println("New client connected")
}
server.OnClose = func(conn *gows.Connection, code int, reason string) {
fmt.Println("Client disconnected:", reason)
}
Each connection holds a thread-safe key-value store:
conn.SetString("username", "alice")
user, exists := conn.GetString("username")
conn.SendText("Hello Client!")
conn.SendJSON(struct {
Event string
Data string
}{
Event: "greeting",
Data: "Hello!",
})
client, err := gows.NewClient("ws://localhost:3000/ws")
if err != nil {
panic(err)
}
client.OnMessage = func(messageType int, msg []byte) {
fmt.Println("Received:", string(msg))
}
// Client
req := map[string]interface{}{"method": "ping"}
resp, timedOut, err := client.SendPrivateMessage(req)
// Server
conn.OnRequest = func(msg []byte, req *gows.ResponseHandler) {
res := map[string]interface{}{"reply": "pong"}
req.Reply(res)
}
- Both client and server can initiate requests.
- Uses a private field like "id" to match requests/responses.
- Customize this field name using SetRequestIdPropertyName().
Typed dispatching of messages using JSON structure matching:
type Candlestick struct {
Timestamp int64
Open float64
High float64
Low float64
Close float64
Volume float64
}
gows.RegisterMessageParserCallback(
client.GetParserRegistry(),
func(b []byte) (bool, *Candlestick) { // Parser function, make sure to be overly explicit, a <nil> error from Unmarshal isn't enough
var c Candlestick
err := json.Unmarshal(b, &c)
return err == nil && c.Timestamp > 0, &c
},
func(c *Candlestick) { // Callback
fmt.Println("Parsed candlestick:", c)
},
)
func(b []byte) (bool, *YourType)
- bool: whether this message matches
- *YourType: parsed struct to forward to the callback
Alternatively, pass nil for the parser to use default json.Unmarshal.
cert, certPEM, keyPEM, _ := gows.Certificates.GenerateSelfSignedCert("localhost")
gows.Certificates.SaveCertToFiles(certPEM, keyPEM, "cert.pem", "key.pem")
server.ListenAndServeTLS(443, cert)
Or load certs from files:
server.ListenAndServeTLSWithFiles(443, "cert.pem", "key.pem")
Event | Triggered When |
---|---|
OnConnect |
A new client connects |
OnClose |
A client disconnects |
OnMessage |
Any message received |
OnRequest |
A private message (request) arrives |
OnReconnect |
Client successfully reconnects |
OnError |
Any socket-level error occurs |
server := gows.NewServer("0.0.0.0", "/ws")
server.OnConnect = func(conn *gows.Connection) {
conn.OnMessage = func(_ int, msg []byte) {
conn.SendText("Echo: " + string(msg))
}
}
server.ListenAndServe(9000)
client, _ := gows.NewClient("ws://localhost:9000/ws")
client.OnMessage = func(_ int, msg []byte) {
fmt.Println("Reply:", string(msg))
}
client.SendText("Hello!")
Feel free to submit issues and pull requests. Feedback and improvements are welcome.
If you would like to support my projects, you can donate to the following addresses:
BTC: 19XC9b9gkbNVTB9eTPzjByijmx8gNd2qVR
ETH (ERC20): 0x7e5db6e135da1f4d5de26f7f7d4ed10dada20478
USDT (TRC20): TLHo8zxBpFSTdyuvvCTG4DzXFfDfv49EMu
SOL: B3ZKvA3yCm5gKLb7vucU7nu8RTnp6MEAPpfeySMSMoDc
Thank you for your support!