Creación de un Sistema de Caché Concurrente en Go
Clase 5 de 19 • Curso de Go Avanzado: Concurrencia y Patrones de Diseño
Resumen
¿Cómo crear un sistema de caché en Go?
En el desarrollo de sistemas, es común enfrentar problemas con cálculos costosos y que demandan gran cantidad de tiempo para ser realizados. Un buen ejemplo de esto es el cálculo de la serie de Fibonacci para números grandes. Para evitar recalcular continuamente estos valores, se utiliza un sistema de caché, donde almacenamos los resultados de estos cálculos. Si el mismo cálculo debe repetirse, simplemente se busca el resultado en el caché. Aquí te mostraré cómo construir un sistema de caché concurrente en Go.
¿Cómo definir la función de Fibonacci?
Antes de iniciar con el caché, es fundamental establecer la función de Fibonacci. En esta ocasión, se utiliza una versión recursiva que es computacionalmente intensiva:
func fibonacci(n int) int {
if n <= 1 {
return n
}
return fibonacci(n-1) + fibonacci(n-2)
}
¿Qué estructuras de datos necesitas en Go?
En Go, las estructuras (structs
) son equivalentes a las clases en otros lenguajes. Aquí, la estructura memory
utiliza funciones para gestionar los cálculos de Fibonacci. Además, mapeamos enteros a resultados utilizando un mapa (map
).
type Function func(int) (interface{}, error)
type FunctionResult struct {
value interface{}
err error
}
type Memory struct {
cache map[int]FunctionResult
f Function
}
¿Cómo crear un constructor para el caché?
El constructor se encarga de inicializar nuestra estructura de memoria y preparar el mapa para almacenar los resultados.
func NewCache(f Function) *Memory {
return &Memory{
cache: make(map[int]FunctionResult),
f: f,
}
}
¿Cómo implementar el acceso al caché?
El método get
del caché verifica si el resultado ya existe y lo devuelve; de lo contrario, calcula, almacena y luego retorna el valor.
func (m *Memory) get(key int) (interface{}, error) {
if result, exists := m.cache[key]; exists {
return result.value, result.err
}
value, err := m.f(key)
m.cache[key] = FunctionResult{value, err}
return value, err
}
¿Cómo ejecutar y medir el rendimiento?
Se integran funciones adicionales para probar varios valores y medir el rendimiento mediante el tiempo que toma cada cálculo.
func main() {
cache := NewCache(getFibonacci)
numbers := []int{42, 40, 41, 42, 38}
for _, n := range numbers {
start := time.Now()
value, err := cache.get(n)
if err != nil {
fmt.Printf("Hubo un error: %v\n", err)
continue
}
fmt.Printf("Fib(%d) = %v, calculated in %v\n", n, value, time.Since(start))
}
}
Puedes observar cómo los cálculos posteriores para el mismo número son prácticamente instantáneos, lo que muestra la eficiencia del sistema de caché. construcción de un sistema de caché como este, no solo mejora el rendimiento, sino que también optimiza recursos, haciendo que tus aplicaciones sean mucho más eficientes.
Recuerda que este ejemplo es secuencial, y al avanzar al siguiente nivel, la concurrencia se convertirá en un desafío importante para garantizar la seguridad en el acceso al caché. ¡Espero que continúes aprendiendo y mejorando tus habilidades en Go!