我第一次尝试使用 Redis 进行一些测试,但遇到了一些与HGET/ HSET/的混淆HGETALL。我的主要问题是我需要存储时间,并且我想使用哈希,因为我会不断更新时间。
起初我读到这样的MarshalBinary功能如何拯救我:
func (f Foo) MarshalBinary() ([]byte, error) {
return json.Marshal(f)
}
它所做的是将结构保存为 json 字符串,但仅保存为字符串,而不是实际的 Redis 哈希。我最终做的是一个相当大的样板代码,它使我想要保存到地图中的结构,并且该结构作为哈希正确存储在 Redis 中。
type Foo struct {
Number int `json:"number"`
ATime time.Time `json:"atime"`
String string `json:"astring"`
}
func (f Foo) toRedis() map[string]interface{} {
res := make(map[string]interface{})
rt := reflect.TypeOf(f)
rv := reflect.ValueOf(f)
if rt.Kind() == reflect.Ptr {
rt = rt.Elem()
rv = rv.Elem()
}
for i := 0; i < rt.NumField(); i++ {
f := rt.Field(i)
v := rv.Field(i)
switch t := v.Interface().(type) {
case time.Time:
res[f.Tag.Get("json")] = t.Format(time.RFC3339)
default:
res[f.Tag.Get("json")] = t
}
}
return res
}
完整的代码在这里
我在想一定有更明智的方法来解决这个问题?还是我被迫做这样的事情?我需要存储的结构只包含整数、字符串和 time.Times。
*edit 评论字段有点短,所以改为编辑:
我最初确实像评论中建议的“傻瓜”一样解决了它并作为答案。我更改为上述部分的原因是,虽然解决方案更复杂,但我认为它对于更改更健壮。如果我使用硬编码地图解决方案,我“必须”拥有:
带有字段散列键的常量,因为它们至少会在两个地方使用(来自和到 Redis),所以它会成为编译器未发现的愚蠢错误的地方。当然可以跳过,但知道我自己的拼写很可能会发生
如果有人只是想添加一个新字段并且不太了解代码,它会编译得很好但是不会在 Redis 中添加新字段。一个容易犯的错误,尤其是对于有点天真的初级开发人员或过于自信的高级开发人员。
我可以将这些辅助函数放在一个库中,当需要时间或复杂类型时,我们所有的代码都会神奇地工作。
不过,我打算提出的问题/希望是:我真的必须像这样跳过箍才能使用 go 将时间存储在 Redis 哈希中吗?公平,time.Time 不是原始数据,Redis 也不是(非)sql 数据库,但我认为缓存中的时间戳是一个非常常见的用例(在我的例子中是一个心跳,用于跟踪超时会话和元数据足以永久存储它,因此需要更新它们)。但也许我滥用了 Redis,我宁愿有两个条目,一个用于数据,一个用于时间戳,这样我就可以使用两个简单的获取/设置函数获取 time.Time 和返回 time.Time。
呼如林
相关分类