go - 有没有更好的方法使用 channel 来确保同步访问 map ?

标签 go maps channels

我使用 Go 映射作为内存缓存和 channel 来确保同步访问。

我的“ session ”包将缓存定义为:map[string]*SessionData

SessionData 是一个也在包中定义的结构,以及代码中看到的其他访问函数。

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

最佳答案

使用 mutex来保护 map 。互斥体通常比使用 channel 和协程来保护资源更简单。

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
}

像这样使用它:

sd := session.GetSessionFromCache(sessTkn) 

关于go - 有没有更好的方法使用 channel 来确保同步访问 map ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44252852/

相关文章:

string - 垃圾回收和Go中指针的正确用法

amazon-web-services - Golang上传Http请求FormFile到Amazon S3

go - Go Rand 包的难度

iphone - 使用自定义注释时 MapKit 蓝点不可见

java - Android:为谷歌地图设置 API key

google-maps - 如何在 Leaflet 中加载谷歌地图基础层(2018 年 6 月之后)?

去教程: Channels and Buffered Channels

Django Channels 从 Celery 任务发送组消息。异步事件循环在所有异步任务完成之前停止

go - 如何使用Gin JWT中间件设置cookie

python - 为什么调整图像大小会导致 channel 数增加?