El patrón de diseño Singleton es uno de los más importantes y utilizados con frecuencia en la programación de software. Garantiza que una clase tenga una sola instancia durante el tiempo de ejecución de la aplicación y proporciona un punto de acceso global a esa instancia. En este artículo, analizaremos la importancia de Singleton, cómo implementarlo en Golang y los beneficios que aporta, especialmente en entornos concurrentes.
Singleton es un patrón de diseño que restringe la instancia de una clase a una sola instancia. Es particularmente útil en situaciones donde se requiere un único punto de control o un único recurso compartido, como por ejemplo:
Voy a enumerar algunos puntos sobre la implementación de Pattern que tienen más sentido y también para mostrar que no todo es color de rosa, algunos de los problemas que podemos tener con ello.
Para implementar un singleton usaré Golang. En este lenguaje tenemos que prestar especial atención a la concurrencia para garantizar que solo se cree una instancia, incluso cuando varias gorutinas intentan acceder a la instancia simultáneamente.
Para acercar nuestro ejemplo al mundo real, creemos un registrador para nuestra aplicación. Un registrador es una herramienta común en aplicaciones que debe ser única para garantizar la coherencia del registro.
Primero, definimos la estructura que queremos que tenga una sola instancia.
package logger import ( "fmt" "sync" ) type Logger struct {} var loggerInstance *Logger
La función NewInstance es responsable de devolver la instancia única de la estructura Singleton. Usamos un mutex para garantizar la seguridad en entornos concurrentes, implementando un bloqueo de doble verificación para mayor eficiencia.
package logger import ( "fmt" "sync" ) type Logger struct{} var logger *Logger var mtx = &sync.Mutex{} func NewInstance() *Logger { if logger == nil { mtx.Lock() defer mtx.Unlock() if logger == nil { fmt.Println("Creating new Logger") logger = &Logger{} } } else { fmt.Println("Logger already created") } return logger }
Una herramienta de registro siempre tiene algunos tipos de registro, como Información para mostrar solo la información, Error para mostrar errores, etc. Es una forma de filtrar también el tipo de información que queremos mostrar en nuestra aplicación.
Entonces, creemos un método que mostrará nuestro registro con el tipo de información. Para hacer esto, crearemos una función que recibirá nuestro mensaje de registro y lo formateará en formato INFO.
package logger import ( "fmt" "sync" "time" ) const ( INFO string = "INFO" ) type Logger struct{} var logger *Logger var mtx = &sync.Mutex{} func NewInstance() *Logger { if logger == nil { mtx.Lock() defer mtx.Unlock() if logger == nil { fmt.Println("Creating new logger") logger = &Logger{} } } else { fmt.Println("Logger already created") } return logger } func (l *Logger) Info(message string) { fmt.Printf("%s - %s: %s\n", time.Now().UTC().Format(time.RFC3339Nano), INFO, message) }
Y para usar nuestro nuevo registrador, crearemos una instancia dentro de nuestro paquete principal y crearemos un registro para ver cómo funciona esta implementación.
package main import ( "playground-go/pkg/logger" ) func main() { log := logger.NewInstance() log.Info("This is an example of log") }
Este es el resultado cuando ejecutamos el programa:
Creating new logger 2024-07-03T19:34:57.609599Z - INFO: This is an example of log
Si queremos probar si NewInstance realmente garantiza que solo tendremos una instancia ejecutándose, podemos hacer la siguiente prueba.
package main import ( "fmt" "playground-go/pkg/logger" ) func main() { log := logger.NewInstance() log.Info("This is an example of log") log2 := logger.NewInstance() log2.Info("This is another example of log") if log == log2 { fmt.Println("same instance") } else { fmt.Println("different instance") } }
Nuestros registros han cambiado y ahora podemos ver que bloqueamos la creación de una nueva instancia:
Creating new logger 2024-07-03T19:45:19.603783Z - INFO: This is an example of log Logger already created 2024-07-03T19:45:19.603793Z - INFO: This is another example of log same instance
El patrón Singleton es una herramienta poderosa para garantizar que solo exista una instancia de una clase específica durante el tiempo de ejecución de la aplicación. En el ejemplo del registrador, vimos cómo se puede aplicar este patrón para garantizar la coherencia del registro en toda la aplicación.
Espero que esto te ayude a comprender mejor Singleton en Golang.
Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.
Copyright© 2022 湘ICP备2022001581号-3