gocache注意事项
先看一下这段代码
func TestTest53(t *testing.T) {
c := cache.New(time.Minute*5, time.Minute*5)
key := "test"
type TmpA struct {
Val int `json:"val"`
}
a := &TmpA{
Val: 1,
}
c.Set(key, a, time.Minute*5)
tmp, _ := c.Get(key)
a2 := tmp.(*TmpA)
fmt.Println(a2.Val)
a2.Val = 2
tmp2, _ := c.Get(key)
a3 := tmp2.(*TmpA)
fmt.Println(a3.Val)
}
// 执行结果为1,2
如果gocache中存的是一个指针,那么通过从gocache中获取数据并重新赋值会修改这个原本的值
不要在并发的情况下在gocache中存可能会被修改数据的指针
假设我们有如下的场景
- 获取礼物信息,礼物信息中有gift_name字段(这是个多语言key,后续需要用相应的语言来替换掉这个字段原有的数据)
- 先从gocache中查礼物信息,如果没有的话,从数据库查,然后set到gocache中,此时gift_name字段为’gift_1_name’
- 然后需要根据用户的多语言来对其进行重新赋值,假设语言为中文,那么gift_name字段变为’礼物1’(注意此时对这个字段进行了修改,假设之前存的是指针,那么在此修改之后的cache中存的gift_name就是’礼物1’,这在线上环境容易出现问题)
- 此次请求正确返回,没有问题
- 又来一个请求,语言为英文,从gocache中获取到了数据,并且此时gift_name为’礼物1’,通过这个gift_name应该无法获得对应多语言,出现问题。
- 更糟糕的是,假设在某种特殊情况下,把某个字段置为了nil,然后另一个请求在不知情的情况下访问了这个nil字段的某个属性或者方法,就会导致panic