--- name: ws_send kind: function lang: go domain: infra version: "1.0.0" purity: impure signature: "func WSSend(client *WSClient, msg []byte) error" description: "Envia bytes al canal Send de un cliente WebSocket especifico de forma no bloqueante. Si el canal esta lleno o el cliente desconectado, retorna error sin bloquear al emisor. Para broadcast a todos los clientes del hub usar WSBroadcast en su lugar." tags: [websocket, send, server, infra, realtime] uses_functions: [] uses_types: [WSClient_go_infra] returns: [] returns_optional: false error_type: "error_go_core" imports: [fmt] params: - name: client desc: "*WSClient destinatario. Si es nil retorna error." - name: msg desc: "bytes a enviar. Tipicamente JSON serializado de un WSMessage. Se entregan tal cual al websocket.Conn." output: "error si el canal Send esta lleno (cliente lento) o cerrado (cliente desconectado). Nil si el mensaje se encolo correctamente." tested: true tests: ["envia mensaje al canal Send del cliente", "retorna error si client es nil", "retorna error si el canal esta lleno"] test_file_path: "functions/infra/ws_test.go" file_path: "functions/infra/ws_send.go" --- ## Ejemplo ```go // Enviar mensaje a un cliente especifico (unicast) target := findClientByID(hub, "user-42") err := WSSend(target, []byte(`{"type":"notification","text":"hola"}`)) if err != nil { log.Printf("send failed: %v", err) } ``` ## Notas Funcion no bloqueante: si el cliente no consume su canal `Send`, este se llena y la funcion retorna error inmediatamente en vez de bloquear al emisor. Esto previene que un cliente lento bloquee a otros productores. El mensaje se encola en `client.Send` — la goroutine writePump del cliente lo escribira al `websocket.Conn`. No hay garantia de orden estricto entre llamadas concurrentes a `WSSend` sobre el mismo cliente.