2017-05-30 2 views
0

J'utilise Go maps comme mémoire cache et canaux pour assurer un accès synchrone.Y a-t-il une meilleure façon d'utiliser les canaux pour assurer un accès synchrone à la carte?

Mon paquet « session » définit le cache comme: carte [chaîne] * SessionData

SessionData est un struct également défini dans le paquet, ainsi que d'autres fonctions d'accès comme on le voit dans le code.

GetWebPage(rw http.ResponseWriter, req *http.Request) { 
var sd *session.SessionData 
var sessTkn string 

cookie, err := req.Cookie("sesstoken") 

if err == nil { // cookie found 
    sessTkn = cookie.Value 
    // Check for cache entry for this token, 
    // using a channel to protect the map and return 
    // a pointer to the cached data if it exists 
    sdc := make(chan *session.SessionData, 1) 
    go session.GetSessionFromCache(sessTkn, sdc) 
    sd = <-sdc 

    if sd == nil { // sessTkn not in the cache 

     // This is test data to simplify example 
     sv := make([]string, 4) 
     sv[0] = sessTkn 
     iv := make([]int, 3) 
     iv[0] = 100 
     iv[1] = 1000 

     sdc := make(chan *session.SessionData, 1) 
     go session.NewSessionData(sv, iv, false, false, sdc) 
     session.SC[sessTkn] = <-sdc 
    } 

// Is this necessary? Is there a better way? 
// ---------------------------------------  
    if sd == nil { 
     sdc = make(chan *session.SessionData, 1) 
     go session.GetSessionFromCache(sessTkn, sdc) 
     sd = <-sdc  
    } 
// ---------------------------------------  

    fmt.Println(sd) // just to prove that it works in both cases 
} 
// The rest of the handler code follows 
+0

Pour assurer un accès synchrone, vous pouvez utiliser [paquet Sémaphore dans Go] (https://github.com/kamilsk/semaphore) –

+0

@Hamza Merci pour la suggestion. Dans mon cas, un sémaphore à usage général sacrifie la capacité à communiquer (envoyer et recevoir des données typées sur le canal). Comme un effet secondaire souhaitable, le canal bloque l'accès à la carte, assurant un accès asynchrone. Aucune des fonctions d'accès ne peut être qualifiée de "levage lourd". Le code fonctionne, Ma seule préoccupation est la répétition nécessaire pour vérifier qu'une nouvelle entrée a été ajoutée à la carte. – emadera52

Répondre

4

Utilisez un mutex pour protéger la carte. Un mutex est souvent plus simple que l'utilisation des canaux & goroutines pour protéger une ressource.

var (
    mu sync.Mutex 
    cache = make(map[string]*SessionData) 
) 

func GetSessionFromCache(sessTkn string) *SessionData { 
    mu.Lock() 
    defer mu.Unlock() 
    sd := cache[sessTkn] 
    if sd != nil { 
     return sd 
    } 
    sd := &SessionData{ 
    // initialize new value here 
    } 
    cache[sessTkn] = sd 
    return sd 
} 

utiliser comme ceci:

sd := session.GetSessionFromCache(sessTkn) 
+0

Merci pour ça. J'avais commencé à planifier d'utiliser un mutex pour la synchronisation. Ensuite, j'ai lu que pour les applications de niveau supérieur, l'utilisation des canaux est meilleure, en particulier lors du partage d'une valeur de données. J'ai clairement mal compris. Retour au plan A. – emadera52

1

Utilisation des canaux pour ce cas particulier ne présentent aucun avantage supplémentaire. Si vous y réfléchissez, même avec la création de nouveaux canaux, vous pouvez toujours avoir un goroutine qui peut accéder à la carte. Comme il n'y a aucun avantage de concurrence ici, utilisez simplement sync.Mutex.

package session 

import "sync" 

var cache = struct { 
    sync.Mutex 
    list map[string]*SessionData 
}{ 
    list: make(map[string]*SessionData), 
} 

func GetSessionFromCache(token string) *SessionData { 
    cache.Lock() 
    defer cache.Unlock() 
    return cache.list[token] 
} 

Ensuite, pas besoin d'une nouvelle goroutine. Appelez-le directement.

sd := session.GetSessionFromCache(sessTkn) 
+0

Merci pour les informations supplémentaires sur les raisons pour lesquelles les chaînes ne sont pas le chemin à parcourir. J'ai besoin de faire d'autres études pour bien comprendre exactement ce que les canaux font et quand leur utilisation est appropriée. – emadera52