为了账号安全,请及时绑定邮箱和手机立即绑定

种族(?) 与互斥体 - 地图中的数据损坏

种族(?) 与互斥体 - 地图中的数据损坏

Go
桃花长相依 2022-08-24 10:46:47
在项目中,我想使用缓存来存储哈希之类的东西。但是,缓存中存储的值会不时更改为密钥。通常从密钥中选取大约 4 个字符:<- Set hash::helloworldtest = abcdef0123456789-> Get hash::helloworldtest = testef0123456789这大致是我的缓存的结构:type node struct {    expires nodeExpiration    value   interface{}}// ...func (c *Cache) Set(key string, value interface{}, expiration time.Duration) {    c.mu.Lock()    c.val[key] = &node{        expires: c.expiration(expiration),        value:   value,    }    // fmt.Println( ... )    c.mu.Unlock()}func (c *Cache) Get(key string) (interface{}, bool) {    c.mu.Lock()    if v, o := c.val[key]; o && v != nil {        if !v.expires.IsExpired() {            // fmt.Println( ... )            c.mu.Unlock()            return v.value, true        }    }    c.mu.Unlock()    return nil, false}// Cache Backendfunc (b *CacheBackend) GetHash(key string) (res string, err error) {    return b.get("hash::" + key)}func (b *CacheBackend) get(key string) (res string, err error) {    if v, ok := b.cache.Get(key); ok {        if s, ok := v.(string); ok {            return s, nil        }        return "", b.errCast    }    return "", nil}// go-fiber Routefunc (s *WebServer) handleGetHashAnywhere(ctx *fiber.Ctx) (err error) {    path := ctx.Params("anywhere")    var res string    if res, err = s.Backend.GetHash(path); err != nil {        return    }    if res == "" {        ctx.Status(404)    } else {        ctx.Status(200)    }    return ctx.SendString(res)}我以前使用过 a,但用 一个 替换了它,认为这可能是问题所在。但与.sync.RWMutexsync.Mutexsync.MutexGet 和 Set 方法在 goroutine 中由 go-fiber 调用,然后返回这些值。有没有人知道这样的事情是如何发生的?编辑1:保存而不是工作正常。[]bytestring
查看完整描述

1 回答

?
慕侠2389804

TA贡献1719条经验 获得超6个赞

该问题在零分配下的文档中进行了描述。摘录:

由于纤程针对高性能进行了优化,因此从纤程返回的值。默认情况下,Ctx 不是不可变的,并且将在请求之间重复使用。[...]一旦您从处理程序返回,您从上下文中获得的任何值都将在将来的请求中重复使用,并将在您的脚下更改。

因此,必须复制上下文值,或者必须在纤程配置中传递“不可变”标志。

第一种解决方案:
从读取值中新建缓冲区并复制其内容

buf := bytes.NewBufferString(ctx.Params("hash"))
hash := string(buf.Bytes())

第二种解决方案:
使用此处描述的内置函数。utils#CopyString(string)

hash := utils.CopyString(ctx.Params("hash"))

第三个解决方案:
不可变的配置标志

cfg := &fiber.Config{Immutable: true}

然后一切正常。


查看完整回答
反对 回复 2022-08-24
  • 1 回答
  • 0 关注
  • 83 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信