【发布时间】:2019-12-13 13:46:23
【问题描述】:
我正在尝试为 Google DataStore 编写 Go 自定义缓存(更准确地说 - 围绕现有缓存库之一的包装器)。在缓存初始化时,它应该接受任何自定义类型的结构(带有适当定义的数据存储字段),这将成为所有存储项目的基础。这个想法是可以为各种类型创建/初始化缓存,这些类型反映了特定 DataStore 条目的结构 (CustomEntry)
方法 1 - 存储 reflect.Type 并使用它。 遇到的问题 - 无法遍历自定义类型的切片
type CustomEntry struct {
Data struct {
name string `datastore:"name,noindex"`
address []string `datastore:"address,noindex"`
} `datastore:"data,noindex"`
}
func (cache *MyCache) CacheData(dataQuery string, dataType reflect.Type) {
slice := reflect.MakeSlice(reflect.SliceOf(dataType), 10, 10)
if keys, err := DataStoreClient.GetAll(cache.ctx, datastore.NewQuery(dataQuery), &slice); err != nil {
//handle error
} else {
for i, dataEntry:= range slice {
// ERROR: Cannot range over 'slice' (type Value)
cache.Set(keys[i].Name, dataEntry)
}
}
//usage: Cache.CacheData("Person", reflect.TypeOf(CustomEntry{})
方法 2 - 接受接口数组作为参数。 遇到的问题 = []CustomEntry 不是[]interface{}
func (cache *MyCache) CacheData(dataQuery string, dataType []interface{}) {
if keys, err := DataStoreClient.GetAll(cache.ctx, datastore.NewQuery(dataQuery), &dataType); err != nil {
//handle error
} else {
for i, dataEntry:= range slice {
// this seems to work fine
cache.Set(keys[i].Name, dataEntry)
}
}
//usage:
var dataType []CustomEntry
Cache.CacheData("Person", data)
// ERROR: Cannot use 'data' (type []CustomEntry) as type []interface{}
任何建议将不胜感激。
【问题讨论】:
-
你查过stackoverflow.com/a/34163477/4466350这样的Q吗?
-
是的,我进行了广泛而深入的搜索。通常的解决方案是在迭代之前简单地进行类型断言,但是 - 据我了解 - 这不能通过反射来完成(当您事先不知道您实际断言的类型时)。这就是为什么我认为提供更多关于我的用例的上下文可能会引导一些更有经验的人找到一些潜在的解决方法。
-
Go 中没有动态类型。
-
@Zack 缓存或无缓存,如果您希望它们被声明它们的包之外的包访问,请不要使用未导出的字段。
reflect.MakeSlice返回一个reflect.Value类型的值,因此将&slice传递给GetAll是错误的,并且试图通过slice传递range也是错误的。查看reflect包的文档以了解如何从slice获取*[]<CustomType>(这是您需要传递给GetAll)以及如何迭代any 的元素reflect.Value包含的切片。
标签: go