Il pourrait être rendu thread-safe en utilisant un mutex, comme @ThunderCat l'a suggéré, mais je pense que cela n'ajoute pas de concurrence. Si deux ou plusieurs requêtes sont faites simultanément, l'une devra attendre que l'autre se termine d'abord, ralentissant le serveur.
Ajout de concurrence: Vous pouvez le rendre plus rapide et gérer davantage de demandes concurrentes en utilisant une file d'attente (qui est un canal Go) et un worker qui écoute ce canal - ce sera une implémentation simple. Chaque fois qu'un message arrive via une requête Post, vous l'ajoutez à la file d'attente (ceci est instantané et la réponse HTTP peut être envoyée immédiatement). Dans une autre goroutine, lorsque vous détectez qu'un message a été ajouté à la file d'attente, vous le retirez et l'ajoutez à votre slice Messages. Pendant que vous ajoutez à Messages, les requêtes HTTP n'ont pas à attendre.
Note : Vous pouvez améliorer en ayant plusieurs goroutines écoutant la file d'attente, mais nous pouvons laisser cela pour plus tard.
Voici à quoi ressemblera plus ou moins le code :
type Message struct {
Text string
User string
Timestamp time.Time
}
var Messages = []Message{}
// messageQueue est la file d'attente qui contient les nouveaux messages jusqu'à ce qu'ils soient traités
var messageQueue chan Message
func init() { // besoin de la fonction init pour initialiser le canal, et les écouteurs
// initialiser la file d'attente, en choisissant la taille du tampon à 8 (nombre de messages que le canal peut contenir à la fois)
messageQueue = make(chan Message, 8)
// démarrer une goroutine qui écoute la file d'attente/canal pour les nouveaux messages
go listenForMessages()
}
func listenForMessages() {
// chaque fois que nous détectons un message dans la file d'attente, l'ajouter à Messages
for m := range messageQueue {
Messages = append(Messages, m)
}
}
func messagePost(c http.ResponseWriter, req *http.Request){
decoder := json.NewDecoder(req.Body)
var m Message
err := decoder.Decode(&m)
if err != nil {
panic(err)
}
if m.Timestamp == (time.Time{}) {
m.Timestamp = time.Now()
}
addUser(m.User)
// ajouter le message au canal, il n'attendra que si le canal est plein
messageQueue <- m
}
Stockage des messages: Comme d'autres utilisateurs l'ont suggéré, stocker les messages en mémoire peut ne pas être le bon choix car les messages ne persisteront pas si l'application est redémarrée. Si vous travaillez sur un petit projet de type concept de preuve et que vous ne voulez pas configurer la DB, vous pourriez enregistrer la variable Messages en tant que fichier plat sur le serveur et ensuite lire à partir de celui-ci à chaque démarrage de l'application (*Note : cela ne devrait pas être fait sur un système de production, bien sûr, pour cela vous devriez mettre en place une base de données). Mais oui, la base de données devrait être la solution à adopter.