Faker en Go: generador de datos falsos

Introducción

Hace algún tiempo desarrollé un seeder en Go, y para ello tuve que usar un faker o generador de datos falsos. Un faker, como yo lo defino, es algo que genera datos aleatorios falsos pero que parecen reales. Por ejemplo, generar un nombre como Marta Pérez Hernández o un número de teléfono como 2116258745. Pues hoy veremos un ejemplo de faker en Go.

Estos datos aunque parecen reales, no se sabe a ciencia cierta si lo son. Pero la mayoría de veces sirven para llenar bases de datos, así no nos quebramos la cabeza en inventar cosas.

Pues bien, hice un faker que genera nombres de productos, fechas entre años, números de teléfonos y nombres de personas. Está escrito en Go y no necesita ninguna librería adicional.

Faker en Go

Probar

He puesto este código en el Go Playground. Puedes ejecutarlo (haciendo click en Run) antes de ver el post: Click aquí

Por cierto, en el playground siempre dará los mismos resultados debido a la fecha y hora del servidor, pero si ejecutas el código en tu máquina por ti mismo debe funcionar correctamente.

Funcionamiento

Lo que hace este pequeño faker es tomar datos de un arreglo (tomándolos de manera aleatoria) y combinándolos. Por ejemplo, aquí tengo un arreglo de nombres masculinos:

nombresMasculinos := []string{"Aaron", "Adam", "Adrián", "Aitor", "Alberto", "Aleix", "Alejandro", "Alex", "Alonso", "Álvaro", "Ander", "Andrés",
		"Ángel", "Antonio", "Arnau", "Asier", "Biel", "Bruno", "Carlos", "César", "Cristian", "Daniel", "Dario", "David",
		"Diego", "Eduardo", "Enrique", "Eric", "Erik", "Fernando", "Francisco", "Francisco Javier", "Gabriel", "Gael", "Gerard", "Gonzalo",
		"Guillem", "Guillermo", "Héctor", "Hugo", "Ian", "Ignacio", "Iker", "Isaac", "Ismael", "Iván", "Izan", "Jaime",
		"Jan", "Javier", "Jesús", "Joel", "Jon", "Jordi", "Jorge", "José", "José Antonio", "José Manuel", "Juan", "Juan José",
		"Leo", "Lucas", "Luis", "Manuel", "Marc", "Marco", "Marcos", "Mario", "Martín", "Mateo", "Miguel", "Miguel Ángel",
		"Nicolás", "Oliver", "Omar", "Oriol", "Óscar", "Pablo", "Pedro", "Pol", "Rafael", "Raúl", "Rayan",
		"Roberto", "Rodrigo", "Rubén", "Samuel", "Santiago", "Saúl", "Sergio", "Unai", "Víctor", "Yago", "Yeray",}

Y hay otro arreglo de nombres femeninos (para que no se quejen las feministas):

nombresFemeninos := []string{"Abril", "Adriana", "Africa", "Aina", "Ainara", "Ainhoa", "Aitana", "Alba", "Alejandra", "Alexandra", "Alexia", "Alicia", "Alma",
		"Ana", "Andrea", "Ane", "Angela", "Anna", "Ariadna", "Aroa", "Aya", "Beatriz", "Berta", "Blanca", "Candela",
		"Carla", "Carlota", "Carmen", "Carolina", "Celia", "Clara", "Claudia", "Cristina", "Daniela", "Diana", "Elena", "Elsa",
		"Emma", "Erika", "Eva", "Fátima", "Gabriela", "Helena", "Inés", "Irene", "Iria", "Isabel", "Jana", "Jimena",
		"Joan", "Julia", "Laia", "Lara", "Laura", "Leire", "Leyre", "Lidia", "Lola", "Lucía", "Luna", "Malak",
		"Manuela", "Mar", "Mara", "María", "Marina", "Marta", "Martí", "Martina", "Mireia", "Miriam", "Nadia", "Nahia",
		"Naia", "Naiara", "Natalia", "Nayara", "Nerea", "Nil", "Noa", "Noelia", "Nora", "Nuria", "Olivia", "Ona",
		"Paola", "Patricia", "Pau", "Paula", "Raquel", "Rocío", "Salma", "Sandra", "Sara", "Silvia", "Sofía", "Teresa",
		"Valentina", "Valeria", "Vega", "Vera", "Victoria", "Yaiza", "Zoe",}

También hay apellidos.

Entonces con Go seleccionamos un número aleatorio que esté entre 0 y la longitud del arreglo. Para esto usamos Intn del paquete rand. Lo que hace esta función es que devuelve un número entre 0 y el argumento que le pasemos.

Por ejemplo, si llamamos a Intn con 5, puede dar un 0, un 1, un 2, 3 o 4. Pero cuidado aquí: no puede darnos un 5, pues devuelve el número en un intervalo [0, n) en donde, como recordemos, devolverá un número mayor o igual a 0 pero menor a n.

Entonces elegimos un dato aleatorio así:

nombre := nombres[seeder.Intn(len(nombres))]

Si tenemos 5 nombres, la función len devolverá 5, pero si intentamos acceder a esa posición (nombres[5]) marcará un error, pues los arreglos comienzan en 0. Así que está bien que usemos Intn, pues devolverá siempre un número menor al que le damos.

Muéstrame el código

Y bien, aquí el código. Es un struct, que podríamos abstraer como una clase.

package main

import (
	"fmt"
	"math/rand"
	"time"
)

type Faker struct {
	seed *rand.Rand
}

func (f *Faker) fechaAleatoriaEntreAnios(minimo, maximo int) time.Time {
	min := time.Date(minimo, 1, 0, 0, 0, 0, 0, time.UTC).Unix()
	max := time.Date(maximo, 1, 0, 0, 0, 0, 0, time.UTC).Unix()
	delta := max - min
	sec := f.seed.Int63n(delta) + min
	t := time.Unix(sec, 0)
	return t
}

func (f *Faker) numerosAleatorios(cuantos int) string {
	letras := "0123456789"
	b := make([]byte, cuantos)
	for i := range b {
		b[i] = letras[f.seed.Intn(len(letras))]
	}
	return string(b)
}

func (f *Faker) verdura() string {
	verduras := []string{"Jitomate", "Sandía", "Limón", "Tomate", "Zanahoria", "Papaya", "Piña", "Manzana", "Pera"}
	descriptores := []string{"Japonés", "Agrio", "Rojo", "Verde", "Fresco", "Bola", "Maradol", "Prémium"}
	return fmt.Sprintf("%s %s", verduras[f.seed.Intn(len(verduras))], descriptores[f.seed.Intn(len(descriptores))])
}

func (f *Faker) botana() string {
	nombres := []string{"Galletas chokis", "Sabritas", "Fritos", "Crujitos", "Doritos", "Rufles"}
	sabores := []string{"chocolate", "queso", "picante", "chorizo", "sal y limón", "habanero", "jalapeño"}
	return fmt.Sprintf("%s sabor %s %d gramos", nombres[f.seed.Intn(len(nombres))], sabores[f.seed.Intn(len(sabores))], f.seed.Intn(999))
}

func (f *Faker) refresco() string {
	nombres := []string{"Coca cola", "Pepsi", "Fanta", "Delaware punch", "Boing"}
	sabores := []string{"Guayaba", "Fresa", "Naranja", "Tamarindo", "Mango"}
	return fmt.Sprintf("%s %d ml sabor %s", nombres[f.seed.Intn(len(nombres))], f.seed.Intn(500), sabores[f.seed.Intn(len(sabores))])
}

func (f *Faker) electronico() string {
	nombres := []string{"Tableta", "Teléfono", "Computadora", "Procesador", "Mouse", "Teclado",}
	marcas := []string{"Samsung", "Xiaomi", "Nokia", "Blackberry", "Intel", "AMD", "Compaq", "HP", "Mac"}
	colores := []string{"Dorado", "Plateado", "Azul", "Blanco", "Rosa"}
	return fmt.Sprintf("%s %s color %s", nombres[f.seed.Intn(len(nombres))], marcas[f.seed.Intn(len(marcas))], colores[f.seed.Intn(len(colores))])
}

func (f *Faker) producto() string {
	numero := f.seed.Intn(4)
	switch numero {
	case 1:
		return f.verdura()
		break
	case 2:
		return f.botana()
		break
	case 3:
		return f.refresco()
		break
	case 4:
		return f.electronico()
		break
	}
	return f.electronico()
}

func (f *Faker) nombre() string {
	nombresMasculinos := []string{"Aaron", "Adam", "Adrián", "Aitor", "Alberto", "Aleix", "Alejandro", "Alex", "Alonso", "Álvaro", "Ander", "Andrés",
		"Ángel", "Antonio", "Arnau", "Asier", "Biel", "Bruno", "Carlos", "César", "Cristian", "Daniel", "Dario", "David",
		"Diego", "Eduardo", "Enrique", "Eric", "Erik", "Fernando", "Francisco", "Francisco Javier", "Gabriel", "Gael", "Gerard", "Gonzalo",
		"Guillem", "Guillermo", "Héctor", "Hugo", "Ian", "Ignacio", "Iker", "Isaac", "Ismael", "Iván", "Izan", "Jaime",
		"Jan", "Javier", "Jesús", "Joel", "Jon", "Jordi", "Jorge", "José", "José Antonio", "José Manuel", "Juan", "Juan José",
		"Leo", "Lucas", "Luis", "Manuel", "Marc", "Marco", "Marcos", "Mario", "Martín", "Mateo", "Miguel", "Miguel Ángel",
		"Nicolás", "Oliver", "Omar", "Oriol", "Óscar", "Pablo", "Pedro", "Pol", "Rafael", "Raúl", "Rayan",
		"Roberto", "Rodrigo", "Rubén", "Samuel", "Santiago", "Saúl", "Sergio", "Unai", "Víctor", "Yago", "Yeray",}

	nombresFemeninos := []string{"Abril", "Adriana", "Africa", "Aina", "Ainara", "Ainhoa", "Aitana", "Alba", "Alejandra", "Alexandra", "Alexia", "Alicia", "Alma",
		"Ana", "Andrea", "Ane", "Angela", "Anna", "Ariadna", "Aroa", "Aya", "Beatriz", "Berta", "Blanca", "Candela",
		"Carla", "Carlota", "Carmen", "Carolina", "Celia", "Clara", "Claudia", "Cristina", "Daniela", "Diana", "Elena", "Elsa",
		"Emma", "Erika", "Eva", "Fátima", "Gabriela", "Helena", "Inés", "Irene", "Iria", "Isabel", "Jana", "Jimena",
		"Joan", "Julia", "Laia", "Lara", "Laura", "Leire", "Leyre", "Lidia", "Lola", "Lucía", "Luna", "Malak",
		"Manuela", "Mar", "Mara", "María", "Marina", "Marta", "Martí", "Martina", "Mireia", "Miriam", "Nadia", "Nahia",
		"Naia", "Naiara", "Natalia", "Nayara", "Nerea", "Nil", "Noa", "Noelia", "Nora", "Nuria", "Olivia", "Ona",
		"Paola", "Patricia", "Pau", "Paula", "Raquel", "Rocío", "Salma", "Sandra", "Sara", "Silvia", "Sofía", "Teresa",
		"Valentina", "Valeria", "Vega", "Vera", "Victoria", "Yaiza", "Zoe",}

	apellidos := []string{"Abad", "Abeyta", "Abrego", "Abreu", "Acevedo", "Acosta", "Acuña", "Adame", "Adorno", "Agosto", "Aguado",
		"Aguayo", "Aguilar", "Aguilera", "Aguirre", "Alanis", "Alaniz", "Alarcón", "Alba", "Alcala", "Alcaráz", "Alcántar", "Alejandro",
		"Alemán", "Alfaro", "Alfonso", "Alicea", "Almanza", "Almaráz", "Almonte", "Alonso", "Alonzo", "Altamirano", "Alva", "Alvarado",
		"Amador", "Amaya", "Anaya", "Andreu", "Andrés", "Anguiano", "Angulo", "Antón", "Aparicio", "Apodaca", "Aponte", "Aragón",
		"Aranda", "Araña", "Arce", "Archuleta", "Arellano", "Arenas", "Arevalo", "Arguello", "Arias", "Armas", "Armendáriz", "Armenta",
		"Armijo", "Arredondo", "Arreola", "Arriaga", "Arribas", "Arroyo", "Arteaga", "Asensio", "Atencio", "Avilés", "Ayala", "Baca",
		"Badillo", "Baeza", "Bahena", "Balderas", "Ballesteros", "Banda", "Barajas", "Barela", "Barragán", "Barraza", "Barrera",
		"Barreto", "Barrientos", "Barrios", "Barroso", "Batista", "Bautista", "Bañuelos", "Becerra", "Beltrán", "Benavides",
		"Benavídez", "Benito", "Benítez", "Bermejo", "Bermúdez", "Bernal", "Berríos", "Blanco", "Blasco", "Blázquez", "Bonilla",
		"Borrego", "Botello", "Bravo", "Briones", "Briseño", "Brito", "Bueno", "Burgos", "Bustamante", "Bustos", "Báez", "Betancourt",
		"Caballero", "Cabello", "Cabrera", "Cabán", "Cadena", "Caldera", "Calderón", "Calero", "Calvillo", "Calvo", "Camacho",
		"Camarillo", "Campos", "Canales", "Candelaria", "Cano", "Cantú", "Caraballo", "Carbajal", "Carballo", "Carbonell",
		"Cárdenas", "Cardona", "Carmona", "Caro", "Carranza", "Carrasco", "Carrasquillo", "Carrera", "Carrero", "Carretero",
		"Carreón", "Carrillo", "Carrión", "Carvajal", "Casado", "Casanova", "Casares", "Casas", "Casillas", "Castañeda", "Castaño",
		"Castellano", "Castellanos", "Castillo", "Castro", "Casárez", "Cavazos", "Cazares", "Ceballos", "Cedillo", "Ceja", "Centeno",
		"Cepeda", "Cerda", "Cervantes", "Cervántez", "Chacón", "Chapa", "Chavarría", "Chávez", "Cintrón", "Cisneros", "Clemente",
		"Cobo", "Collado", "Collazo", "Colunga", "Colón", "Concepción", "Conde", "Contreras", "Cordero", "Cornejo", "Corona",
		"Coronado", "Corral", "Corrales", "Correa", "Cortés", "Cortez", "Cortés", "Costa", "Cotto", "Covarrubias", "Crespo",
		"Cruz", "Cuellar", "Cuenca", "Cuesta", "Cuevas", "Curiel", "Córdoba", "Córdova", "De la Cruz", "De la Fuente",
		"De la Torre", "Del Río", "Delacrúz", "Delafuente", "Delagarza", "Delao", "Delapaz", "Delarosa", "Delatorre", "Deleón",
		"Delgadillo", "Delgado", "Delrío", "Delvalle", "Díez", "Domenech", "Domingo", "Domínguez", "Domínquez", "Duarte",
		"Dueñas", "Duran", "Dávila", "Díaz", "Echevarría", "Elizondo", "Enríquez", "Escalante", "Escamilla", "Escobar", "Escobedo",
		"Escribano", "Escudero", "Esparza", "Espinal", "Espino", "Espinosa", "Espinoza", "Esquibel", "Esquivel", "Esteban", "Esteve",
		"Estrada", "Estévez", "Expósito", "Fajardo", "Farías", "Feliciano", "Fernández", "Ferrer", "Fierro", "Figueroa", "Flores",
		"Flórez", "Fonseca", "Font", "Franco", "Frías", "Fuentes", "Gaitán", "Galarza", "Galindo", "Gallardo", "Gallego", "Gallegos",
		"Galván", "Galán", "Gamboa", "Gámez", "Gaona", "Garay", "García", "Garibay", "Garica", "Garrido", "Garza", "Gastélum",
		"Gaytán", "Gil", "Gimeno", "Giménez", "Girón", "Godoy", "Godínez", "Gonzáles", "González", "Gracia", "Granado", "Granados",
		"Griego", "Grijalva", "Guajardo", "Guardado", "Guerra", "Guerrero", "Guevara", "Guillen", "Gurule", "Gutiérrez", "Guzmán",
		"Gálvez", "Gómez", "Haro", "Henríquez", "Heredia", "Hernándes", "Hernando", "Hernádez", "Hernández", "Herrera", "Herrero",
		"Hidalgo", "Hinojosa", "Holguín", "Huerta", "Hurtado", "Ibarra", "Ibáñez", "Iglesias", "Irizarry", "Izquierdo", "Jaime",
		"Jaimes", "Jaramillo", "Jasso", "Jiménez", "Jimínez", "Juan", "Jurado", "Juárez", "Jáquez", "Laboy", "Lara", "Laureano",
		"Leal", "Lebrón", "Ledesma", "Leiva", "Lemus", "Lerma", "Leyva", "León", "Limón", "Linares", "Lira", "Llamas", "Llorente",
		"Loera", "Lomeli", "Longoria", "Lorente", "Lorenzo", "Lovato", "Loya", "Lozada", "Lozano", "Lucas", "Lucero", "Lucio",
		"Luevano", "Lugo", "Luis", "Luján", "Luna", "Luque", "Lázaro", "López", "Macias", "Macías", "Madera", "Madrid", "Madrigal",
		"Maestas", "Magaña", "Malave", "Maldonado", "Manzanares", "Manzano", "Marco", "Marcos", "Mares", "Marrero", "Marroquín",
		"Martos", "Martí", "Martín", "Martínez", "Marín", "Más", "Mascareñas", "Mata", "Mateo", "Mateos", "Matos", "Matías",
		"Maya", "Mayorga", "Medina", "Medrano", "Mejía", "Melgar", "Meléndez", "Mena", "Menchaca", "Mendoza", "Menéndez",
		"Meraz", "Mercado", "Merino", "Mesa", "Meza", "Miguel", "Millán", "Miramontes", "Miranda", "Mireles", "Mojica", "Molina",
		"Mondragón", "Monroy", "Montalvo", "Montañez", "Montaño", "Montemayor", "Montenegro", "Montero", "Montes", "Montez",
		"Montoya", "Mora", "Moral", "Morales", "Morán", "Moreno", "Mota", "Moya", "Munguía", "Murillo", "Muro", "Muñiz", "Muñoz",
		"Márquez", "Méndez", "Naranjo", "Narváez", "Nava", "Navarrete", "Navarro", "Navas", "Nazario", "Negrete", "Negrón", "Nevárez",
		"Nieto", "Nieves", "Niño", "Noriega", "Nájera", "Núñez", "Ocampo", "Ocasio", "Ochoa", "Ojeda", "Oliva", "Olivares",
		"Olivas", "Oliver", "Olivera", "Olivo", "Olivárez", "Olmos", "Olvera", "Ontiveros", "Oquendo", "Ordoñez", "Ordóñez",
		"Orellana", "Ornelas", "Orosco", "Orozco", "Orta", "Ortega", "Ortíz", "Osorio", "Otero", "Ozuna", "Pabón", "Pacheco",
		"Padilla", "Padrón", "Pagan", "Palacios", "Palomino", "Palomo", "Pantoja", "Pardo", "Paredes", "Parra", "Partida",
		"Pascual", "Pastor", "Patiño", "Paz", "Pedraza", "Pedroza", "Pelayo", "Peláez", "Perales", "Peralta", "Perea", "Pereira",
		"Peres", "Peña", "Pichardo", "Pineda", "Pizarro", "Piña", "Piñeiro", "Plaza", "Polanco", "Polo", "Ponce", "Pons", "Porras",
		"Portillo", "Posada", "Pozo", "Prado", "Preciado", "Prieto", "Puente", "Puga", "Puig", "Pulido", "Páez", "Pérez", "Quesada",
		"Quezada", "Quintana", "Quintanilla", "Quintero", "Quiroz", "Quiñones", "Quiñónez", "Rael", "Ramos", "Ramírez",
		"Ramón", "Rangel", "Rascón", "Raya", "Razo", "Redondo", "Regalado", "Reina", "Rendón", "Rentería", "Requena", "Reséndez",
		"Rey", "Reyes", "Reyna", "Reynoso", "Rico", "Riera", "Rincón", "Riojas", "Rivas", "Rivera", "Rivero", "Robledo", "Robles",
		"Roca", "Rocha", "Rodarte", "Rodrigo", "Rodríguez", "Rodríquez", "Roig", "Rojas", "Rojo", "Roldán", "Rolón", "Romero",
		"Romo", "Román", "Roque", "Ros", "Rosa", "Rosado", "Rosales", "Rosario", "Rosas", "Roybal", "Rubio", "Rueda", "Ruelas",
		"Ruiz", "Ruvalcaba", "Ruíz", "Ríos", "Saavedra", "Saiz", "Salas", "Salazar", "Salcedo", "Salcido", "Saldaña", "Saldivar",
		"Salgado", "Salinas", "Salvador", "Samaniego", "Sanabria", "Sánchez", "Sancho", "Sandoval", "Santacruz", "Santamaría",
		"Santana", "Santiago", "Santillán", "Santos", "Sanz", "Sarabia", "Sauceda", "Saucedo", "Sedillo", "Segovia", "Segura",
		"Sepúlveda", "Serna", "Serra", "Serrano", "Serrato", "Sevilla", "Sierra", "Silva", "Simón", "Sisneros", "Sola", "Solano",
		"Soler", "Soliz", "Solorio", "Solorzano", "Solís", "Soria", "Soriano", "Sosa", "Sotelo", "Soto", "Suárez", "Sáenz",
		"Sáez", "Sánchez", "Tafoya", "Tamayo", "Tamez", "Tapia", "Tejada", "Tejeda", "Tello", "Terrazas", "Terán", "Tijerina",
		"Tirado", "Toledo", "Toro", "Torres", "Tovar", "Trejo", "Treviño", "Trujillo", "Téllez", "Tórrez", "Ulibarri", "Ulloa",
		"Urbina", "Ureña", "Uribe", "Urrutia", "Urías", "Vaca", "Valadez", "Valdez", "Valdivia", "Valdés", "Valencia",
		"Valentín", "Valenzuela", "Valero", "Valladares", "Valle", "Vallejo", "Valles", "Valverde", "Vanegas", "Varela",
		"Vargas", "Vega", "Vela", "Velasco", "Velásquez", "Velázquez", "Venegas", "Vera", "Verdugo", "Verduzco", "Vergara",
		"Vicente", "Vidal", "Viera", "Vigil", "Vila", "Villa", "Villagómez", "Villalba", "Villalobos", "Villalpando", "Villanueva",
		"Villar", "Villareal", "Villarreal", "Villaseñor", "Villegas", "Vásquez", "Vázquez", "Vélez", "Véliz", "Ybarra",
		"Yáñez", "Zambrano", "Zamora", "Zamudio", "Zapata", "Zaragoza", "Zarate", "Zavala", "Zayas", "Zelaya", "Zepeda",
		"Zúñiga", "de Anda", "de Jesús", "Águilar", "Álvarez", "Ávalos", "Ávila",}
	var nombre string
	if f.seed.Intn(2) == 1 {
		nombre = nombresFemeninos[f.seed.Intn(len(nombresFemeninos))]
	} else {
		nombre = nombresMasculinos[f.seed.Intn(len(nombresMasculinos))]
	}
	return fmt.Sprintf("%s %s %s", nombre, apellidos[f.seed.Intn(len(apellidos))], apellidos[f.seed.Intn(len(apellidos))])
}

Para usarlo simplemente creamos una instancia, le pasamos el seeder y listo. Así:

func main() {

	//Necesitamos alimentar el seeder sólo una vez antes de usarlo
	fuente := rand.NewSource(time.Now().Unix())
	random := rand.New(fuente)

	//Creamos una instancia y le pasamos la semilla para poder elegir cosas aleatorias
	faker := Faker{
		seed: random,
	}

	// Hora de usar el faker :-)
	fmt.Printf("Un producto: %s\n", faker.producto())

	//También se puede dentro de un ciclo
	for x := 0; x <= 10; x++ {
		fmt.Printf("Alguna fecha aleatoria entre 2010 y 2020: %v\n", faker.fechaAleatoriaEntreAnios(2010, 2020))
	}

	//Un nombre
	nombre := faker.nombre()
	fmt.Printf("El nombre: %s\n", nombre)

	//Número aleatorio. Como un número telefónico o un código de barras
	numero := faker.numerosAleatorios(10)
	fmt.Printf("Un número aleatorio de 10 dígitos: %s", numero)
}

En mi caso puse todo en el mismo archivo, y al ejecutarlo con go run faker.go obtengo esto:

Probando nuestro faker en Go

Probando nuestro faker en Go

Yo lo utilicé para un seeder y trabaja muy bien. Obviamente tiene algunos “errores” que podemos ver, por ejemplo, no hay tabletas AMD, pero como lo dije, es un faker: datos falsos.

Espero mejorarlo con el tiempo.

 

Faker en Go: generador de datos falsos

Por parzibyte Tiempo de lectura: 9 min
0