Namespace API Reference¶
The Namespace type represents a connection to a specific namespace in Socket.IO. Namespaces allow multiplexing multiple connections over a single WebSocket connection.
Table of Contents¶
Namespace Concept¶
Namespaces are separate communication channels that share the same physical connection. They enable:
- Logical separation: Different areas of your application can use different namespaces
- Efficiency: A single WebSocket connection handles multiple namespaces
- Security: You can control access to specific namespaces
Default Namespace¶
The default namespace is /. When using methods directly on Socket, you are using this namespace:
Obtaining Namespaces¶
Namespaces are obtained through the Of() method of Socket:
// Get custom namespace
chat := client.Of("/chat")
admin := client.Of("/admin")
notifications := client.Of("/notifications")
Event Methods¶
On¶
Registers a handler to listen for a specific event on this namespace.
Parameters: - event (string): Event name - handler (EventHandler): Function executed when the event is received
Example:
chat := client.Of("/chat")
chat.On("message", func(data ...interface{}) {
msg := data[0].(string)
fmt.Printf("Chat message: %s\n", msg)
})
chat.On("user-joined", func(data ...interface{}) {
user := data[0].(map[string]interface{})
fmt.Printf("%s joined the chat\n", user["name"])
})
OnConnect¶
Registers a handler that executes when this namespace successfully connects.
Parameters: - handler (func()): Function executed on connection
Example:
chat := client.Of("/chat")
chat.OnConnect(func() {
fmt.Println("Connected to namespace /chat")
// Emit initial event on this namespace
chat.Emit("join-room", "general")
})
OnDisconnect¶
Registers a handler that executes when this namespace disconnects.
Parameters: - handler (func(reason string)): Function that receives the disconnection reason
Example:
chat := client.Of("/chat")
chat.OnDisconnect(func(reason string) {
fmt.Printf("Disconnected from /chat: %s\n", reason)
})
Emission Methods¶
Emit¶
Emits an event to the server on this namespace.
Parameters: - event (string): Event name - data (...interface{}): Arguments to send
Returns: - error: Error if the operation fails
Example:
chat := client.Of("/chat")
// Emit simple message
chat.Emit("message", "Hello everyone")
// Emit structured data
chat.Emit("action", map[string]interface{}{
"type": "typing",
"user": "john",
})
// Multiple arguments
chat.Emit("chat-message", "john", "Hello", time.Now().Unix())
EmitWithAck¶
Emits an event and waits for an acknowledgment response from the server on this namespace.
Parameters: - event (string): Event name - ack (AckCallback): Callback function that receives the response - data (...interface{}): Arguments to send
Returns: - error: Error if the operation fails
Example:
chat := client.Of("/chat")
chat.EmitWithAck("get-history", func(response ...interface{}) {
if response == nil {
fmt.Println("Timeout waiting for history")
return
}
history := response[0].([]interface{})
fmt.Printf("History received: %d messages\n", len(history))
}, "general-room")
EmitBinary¶
Emits an event with binary data on this namespace.
Parameters: - event (string): Event name - binaryData ([]byte): Binary data to send - data (...interface{}): Additional arguments (optional)
Returns: - error: Error if the operation fails
Example:
chat := client.Of("/chat")
// Read image
imageData, err := os.ReadFile("photo.jpg")
if err != nil {
log.Fatal(err)
}
// Send image with metadata
chat.EmitBinary("image", imageData, map[string]interface{}{
"filename": "photo.jpg",
"from": "user123",
"size": len(imageData),
})
State Methods¶
IsConnected¶
Returns whether this namespace is currently connected.
Returns: - bool: true if connected, false otherwise
Example:
chat := client.Of("/chat")
if chat.IsConnected() {
chat.Emit("ping")
} else {
fmt.Println("Chat namespace is not connected")
}
GetPath¶
Returns the path of this namespace.
Returns: - string: Namespace path (e.g., /chat, /admin)
Example:
Examples¶
Basic Example: Chat Application¶
package main
import (
"fmt"
socketio "github.com/arcaela/socket.io-client-go"
)
func main() {
client := socketio.New("ws://localhost:3000")
defer client.Close()
// Chat namespace
chat := client.Of("/chat")
chat.OnConnect(func() {
fmt.Println("β
Connected to chat")
// Join a room
chat.Emit("join-room", "general")
})
chat.On("message", func(data ...interface{}) {
username := data[0].(string)
message := data[1].(string)
fmt.Printf("π¬ [%s]: %s\n", username, message)
})
chat.On("user-joined", func(data ...interface{}) {
username := data[0].(string)
fmt.Printf("π€ %s joined the chat\n", username)
})
chat.On("user-left", func(data ...interface{}) {
username := data[0].(string)
fmt.Printf("π %s left the chat\n", username)
})
// Send message
chat.Emit("message", "juan", "Hello everyone!")
select {}
}
Example: Multiple Namespaces¶
package main
import (
"fmt"
socketio "github.com/arcaela/socket.io-client-go"
)
func main() {
client := socketio.New("ws://localhost:3000")
defer client.Close()
// Public chat namespace
publicChat := client.Of("/chat")
publicChat.OnConnect(func() {
fmt.Println("β
Public chat connected")
})
publicChat.On("message", func(data ...interface{}) {
fmt.Printf("π¬ [Public] %s: %s\n", data[0], data[1])
})
// Private chat namespace
privateChat := client.Of("/chat/private")
privateChat.OnConnect(func() {
fmt.Println("β
Private chat connected")
})
privateChat.On("message", func(data ...interface{}) {
fmt.Printf("π [Private] %s: %s\n", data[0], data[1])
})
// Notifications namespace
notifications := client.Of("/notifications")
notifications.OnConnect(func() {
fmt.Println("β
Notifications connected")
})
notifications.On("new", func(data ...interface{}) {
notif := data[0].(map[string]interface{})
fmt.Printf("π Notification: %s\n", notif["message"])
})
// Admin namespace (with specific authentication)
admin := client.Of("/admin")
admin.OnConnect(func() {
fmt.Println("β
Admin connected")
admin.Emit("authenticate", map[string]interface{}{
"token": "admin-secret-token",
})
})
admin.On("stats", func(data ...interface{}) {
stats := data[0].(map[string]interface{})
fmt.Printf("π Stats: %v connected users\n", stats["users"])
})
select {}
}
Example: Namespace with Acknowledgments¶
package main
import (
"fmt"
"time"
socketio "github.com/arcaela/socket.io-client-go"
)
func main() {
client := socketio.New("ws://localhost:3000")
defer client.Close()
api := client.Of("/api")
api.OnConnect(func() {
fmt.Println("β
API namespace connected")
// Get user data
api.EmitWithAck("get-user", func(response ...interface{}) {
if response == nil {
fmt.Println("β±οΈ Timeout waiting for user")
return
}
user := response[0].(map[string]interface{})
fmt.Printf("π€ User: %s\n", user["name"])
}, "user-123")
// Create resource
api.EmitWithAck("create-post", func(response ...interface{}) {
if response == nil {
fmt.Println("β±οΈ Timeout creating post")
return
}
result := response[0].(map[string]interface{})
if result["success"].(bool) {
fmt.Printf("β
Post created with ID: %v\n", result["id"])
} else {
fmt.Printf("β Error: %s\n", result["error"])
}
}, map[string]interface{}{
"title": "My first post",
"content": "Post content",
})
})
select {}
}
Example: Namespace with Binary Data¶
package main
import (
"fmt"
"os"
socketio "github.com/arcaela/socket.io-client-go"
)
func main() {
client := socketio.New("ws://localhost:3000")
defer client.Close()
files := client.Of("/files")
files.OnConnect(func() {
fmt.Println("β
Files namespace connected")
// Upload file
uploadFile(files, "document.pdf")
})
files.On("upload-progress", func(data ...interface{}) {
progress := data[0].(map[string]interface{})
fmt.Printf("π€ Progress: %.0f%%\n", progress["percent"])
})
files.On("upload-complete", func(data ...interface{}) {
result := data[0].(map[string]interface{})
fmt.Printf("β
File uploaded: %s\n", result["url"])
})
files.On("file-received", func(data ...interface{}) {
binaryData := data[0].([]byte)
metadata := data[1].(map[string]interface{})
filename := metadata["filename"].(string)
fmt.Printf("π₯ File received: %s (%d bytes)\n", filename, len(binaryData))
// Save file
os.WriteFile(filename, binaryData, 0644)
})
select {}
}
func uploadFile(ns *socketio.Namespace, path string) {
data, err := os.ReadFile(path)
if err != nil {
fmt.Printf("Error reading file: %v\n", err)
return
}
ns.EmitBinary("upload", data, map[string]interface{}{
"filename": path,
"size": len(data),
})
}
Example: Error Handling per Namespace¶
package main
import (
"fmt"
socketio "github.com/arcaela/socket.io-client-go"
)
func main() {
client := socketio.New("ws://localhost:3000")
defer client.Close()
// Namespace that may require special authentication
admin := client.Of("/admin")
admin.OnConnect(func() {
fmt.Println("β
Attempting to authenticate on /admin")
admin.Emit("auth", map[string]interface{}{
"token": "admin-token",
})
})
admin.On("auth-success", func(data ...interface{}) {
fmt.Println("β
Authentication successful on /admin")
admin.Emit("get-stats")
})
admin.On("auth-failed", func(data ...interface{}) {
reason := data[0].(string)
fmt.Printf("β Authentication failed: %s\n", reason)
admin.Emit("disconnect") // Disconnect this namespace
})
admin.On("error", func(data ...interface{}) {
err := data[0].(string)
fmt.Printf("β οΈ Error on /admin: %s\n", err)
})
admin.OnDisconnect(func(reason string) {
fmt.Printf("β /admin disconnected: %s\n", reason)
})
select {}
}
Thread-Safety¶
All Namespace methods are thread-safe and can be called from multiple goroutines.
chat := client.Of("/chat")
// Emit from multiple goroutines
for i := 0; i < 10; i++ {
go func(id int) {
chat.Emit("worker-message", map[string]interface{}{
"worker": id,
"data": processData(id),
})
}(i)
}
Best Practices¶
1. Organize by Functionality¶
// Separate namespaces by functionality
chat := client.Of("/chat")
notifications := client.Of("/notifications")
admin := client.Of("/admin")
2. Verify Connection Before Emitting¶
chat := client.Of("/chat")
if chat.IsConnected() {
chat.Emit("message", "Hello")
} else {
fmt.Println("Chat not connected, queuing message for later")
queueMessage("Hello")
}
3. Handle Connection Events¶
api := client.Of("/api")
api.OnConnect(func() {
// Subscribe to events when connected
api.Emit("subscribe", []string{"users", "posts", "comments"})
})
api.OnDisconnect(func(reason string) {
// Clean up state when disconnected
clearLocalCache()
})
4. Use Acknowledgments for Critical Operations¶
api := client.Of("/api")
api.EmitWithAck("important-operation", func(response ...interface{}) {
if response == nil {
fmt.Println("Operation failed (timeout)")
retryOperation()
return
}
if response[0].(map[string]interface{})["success"].(bool) {
fmt.Println("Operation successful")
}
}, operationData)