Cómo leer desde la entrada estándar en Go: de principiante a profesional
¿Alguna vez se ha preguntado cómo hacer que su programa Go "escuche" al usuario? ¿Cómo escribir una utilidad que acepte comandos desde la consola, o una herramienta CLI interactiva? Si es así, ha llegado al lugar correcto. Hoy analizaremos la lectura desde la entrada estándar (stdin) en Go — con tanto detalle como sea posible.
Este tema es un verdadero éxito en Stack Overflow. La pregunta "How can I read from standard input in the console?" ha acumulado miles de visitas. Y con razón: la entrada estándar es la base sin la cual ningún proyecto serio en Go puede funcionar. Adaptamos esta pregunta para la audiencia hispanohablante y la convertimos en un tutorial completo.
En este artículo aprenderá:
- Qué es
os.Stdiny cómo trabajar con él - Cómo usar
bufio.Scannerpara lectura línea por línea - Por qué
fmt.Scanes un arma de doble filo - Cómo leer archivos completos desde stdin
- Secretos del manejo de errores y rendimiento
¡Allá vamos!
¿Qué es stdin y para qué sirve en Go?
La entrada estándar (stdin) es un flujo de datos que su programa recibe desde la consola o desde otro proceso. En Go está representada por la variable os.Stdin de tipo *os.File. Es la puerta de entrada a través de la cual los datos llegan a su programa.
¿Para qué sirve? Imagine:
- Está escribiendo una utilidad CLI que procesa la entrada del usuario
- Está creando un analizador de logs que lee datos a través de un pipe (
cat log.txt | miapp) - Necesita implementar entrada interactiva con sugerencias
Go, siendo un lenguaje para programación de sistemas, proporciona herramientas elegantes para trabajar con stdin. Analicémoslas en orden.
Método 1: bufio.Scanner — el rey de la lectura línea por línea
La forma más popular y recomendada de leer desde stdin en Go es bufio.Scanner. Es simple, eficiente y resuelve el 90% de las tareas.
Así es como se ve el ejemplo clásico:
package main
import ( "bufio" "fmt" "os")
func main() { scanner := bufio.NewScanner(os.Stdin) fmt.Println("Ingrese texto (Ctrl+D para finalizar):") for scanner.Scan() { line := scanner.Text() fmt.Println("Usted ingresó:", line) } if err := scanner.Err(); err != nil { fmt.Fprintln(os.Stderr, "Error de lectura:", err) }}¿Cómo funciona?
bufio.NewScanner(os.Stdin)— crea un escáner que lee desde la entrada estándarscanner.Scan()— devuelvetruemientras haya datos (por defecto hasta el carácter de nueva línea)scanner.Text()— devuelve la línea actual sin el carácter- El bucle se interrumpe en
EOF(Ctrl+D en Linux/Mac, Ctrl+Z en Windows)
Este código es la base para cualquier entrada de consola en Go. Funciona perfectamente con pipes y entrada interactiva.
Personalización del Scanner
Por defecto, Scanner divide la entrada por líneas. Pero puede cambiar esto:
// Lectura por palabrasscanner.Split(bufio.ScanWords)
// Lectura por bytesscanner.Split(bufio.ScanBytes)
// Lectura por caracteres (runas)scanner.Split(bufio.ScanRunes)También puede definir su propio divisor — por ejemplo, para CSV o separadores personalizados. Pero eso ya es tema para otro artículo.
Método 2: fmt.Scan — rápido y sucio
Si necesita ingresar un solo valor — un número, una cadena o varias variables — fmt.Scan acudirá al rescate. Es como scanf en C, solo que