Le Singleton est un patron de conception de création qui s’assure de l’existence d’un seul objet de son genre et fournit un unique point d’accès vers cet objet.
Le singleton possède à peu près les mêmes avantages et inconvénients que les variables globales. Même s’ils sont super utiles, ils réduisent la modularité du code.
Vous ne pourrez pas utiliser une classe qui dépend d’un singleton dans un autre contexte. Vous devrez également inclure complètement la classe Singleton dans votre code. En général, on se rend compte de cette limitation lorsque l’on crée des tests unitaires.
En général, une instance de singleton est créée lors de la première initialisation de la struct. Pour ce faire, nous définissons la méthode getInstance dans la struct. Cette méthode sera responsable de la création et du renvoi de l’instance du singleton. Une fois créée, cette même instance sera retournée chaque fois que getInstance est appelée.
Qu’en est-il des goroutines ? La struct du singleton doit renvoyer la même instance si plusieurs goroutines tentent d’y accéder. C’est la raison pour laquelle on peut facilement se tromper et mal concevoir notre singleton. L’exemple ci-dessous vous montre la bonne manière de le mettre en place.
Quelques points intéressants à noter :
Il y a un test de nullité au début pour s’assurer que singleInstance est vide la première fois. Ce test permet de ne pas avoir à mettre en place des locks (coûteux) chaque fois que la méthode getInstance est appelée. Si ce test échoue, cela veut dire que l’attribut singleInstance a déjà été initialisé.
La struct singleInstance est créée à l’intérieur du lock.
Il y a un autre test de nullité après avoir placé le lock. Il permet de s’assurer qu’une seule des goroutines parmi celles qui passent la première vérification puisse créer l’instance du singleton. Sinon, toutes les goroutines vont créer leur propre instance du struct singleton.
single.go: Singleton
main.go: Code client
output.txt: Résultat de l’exécution
Autre exemple
Il y a d’autres méthodes pour créer une instance de singleton en Go :
Fonction init
Nous pouvons créer une instance unique à l’intérieur de la fonction init. Ce n’est possible que si l’initialisation précoce de l’instance nous l’accorde. La fonction init n’est appelée qu’une seule fois par fichier dans un package, nous sommes donc certains qu’une seule instance sera créée.
sync.Once
sync.Once ne lancera le traitement qu’une seule fois. Voir le code ci-dessous :