¿Por qué Go es el lenguaje ideal para la programación de redes?
\n\nSi alguna vez has escrito un servidor de red en Python (especialmente usando socket o asyncio), sabes lo rápido que el código puede convertirse en un laberinto de callbacks y bucles de eventos. Go (Golang) resuelve este problema a nivel arquitectónico: las gorutinas y los canales hacen que el trabajo asíncrono con la red sea tan simple como escribir código secuencial.
En este artículo, analizaremos la programación de redes en Go en la práctica. Aprenderás cómo armar un chat TCP completo en 15 minutos, enviar un paquete UDP y ejecutar un servidor HTTP con enrutamiento. Todos los ejemplos son funcionales, se pueden copiar y ejecutar.
\n\nFundamentos: el paquete net y su superpoder
\n\nEn Go, toda la magia de redes vive en el paquete estándar net. Proporciona una interfaz unificada para trabajar con TCP, UDP, sockets Unix e incluso SSL/TLS. La característica principal es que las funciones Listen, Dial y Accept funcionan de forma síncrona, pero no bloquean todo el programa porque cada gorutina es liviana.
Vayamos directo al grano.
\n\nServidor TCP: chat en 10 líneas
\n\nCrearemos un simple servidor eco que acepta conexiones y envía de vuelta lo que recibe. Esto es un clásico de la programación de redes en Go.
\n\npackage main\n\nimport (\n "bufio"\n "fmt"\n "net"\n)\n\nfunc handleConnection(conn net.Conn) {\n defer conn.Close()\n scanner := bufio.NewScanner(conn)\n for scanner.Scan() {\n message := scanner.Text()\n fmt.Printf("Recibido: %s\\n", message)\n conn.Write([]byte("Eco: " + message + "\\n"))\n }\n}\n\nfunc main() {\n listener, _ := net.Listen("tcp", ":8080")\n fmt.Println("Servidor TCP iniciado en :8080")\n for {\n conn, _ := listener.Accept()\n go handleConnection(conn) // cada gorutina es un cliente separado\n }\n}\n\n¿Qué sucede aquí?
\n- \n
net.Listen("tcp", ":8080")— crea un listener TCP en el puerto 8080. \n - El bucle infinito
foracepta nuevas conexiones a través deAccept(). \n - Cada conexión se maneja en una gorutina separada
go handleConnection(). \n - Dentro de la función, leemos líneas usando
bufio.Scannery enviamos una respuesta. \n
Ejecuta este código, abre una terminal y conéctate a través de nc localhost 8080 (o Putty). Cualquier mensaje regresará con el prefijo "Eco:". Sorprendentemente, esto ya es un servidor de red completo, capaz de atender a miles de clientes sin un solo callback.
UDP: entrega rápida sin garantías
\n\nSi TCP es como una llamada telefónica (estableces conexión y hablas), UDP es como las postales: las envías y te olvidas. Go hace que trabajar con UDP sea igual de simple.
\n\nCliente y servidor UDP
\n\n// Servidor\npackage main\n\nimport (\n "fmt"\n "net"\n)\n\nfunc main() {\n addr, _ := net.ResolveUDPAddr("udp", ":8081")\n conn, _ := net.ListenUDP("udp", addr)\n defer conn.Close()\n\n buffer := make([]byte, 1024)\n for {\n n, clientAddr, _ := conn.ReadFromUDP(buffer)\n message := string(buffer[:n])\n fmt.Printf("Recibido de %s: %s\\n", clientAddr, message)\n conn.WriteToUDP([]byte("Recibido: "+message+"\\n"), clientAddr)\n }\n}\n\n// Cliente\n// En un archivo separado o gorutina:\nconn, _ := net.Dial("udp", "localhost:8081")\ndefer conn.Close()\nconn.Write([]byte("¡Hola, UDP!"))\nbuffer := make([]byte, 1024)\nn, _ := conn.Read(buffer)\nfmt.Println(string(buffer[:n]))\n\nDiferencia clave con TCP:
\n- \n
- No hay
Accept()— simplemente escuchamos el puerto y leemos datagramas. \n - Cada paquete llega con su propia dirección de origen. \n
- Go maneja el buffer por sí mismo:
ReadFromUDPBlogs
Book Recommendations
Leer también
Metaprogramación en JavaScript: magia de Proxy, Reflect y Symbol
Por qué C# es popular: del odio al amor y millones de proyectos
Caché en TypeScript: aceleramos la aplicación sin dolor
El secreto de #include en C++: <file> vs "file" — velocidad y optimización
Expresiones regulares en TypeScript: guía completa con ejemplos