如何在自定义类型的切片上进行范围

我正在尝试为 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{}

任何建议将不胜感激。


30秒到达战场
浏览 130回答 1
1回答

杨__羊羊

我找到了一个解决方案,并认为它可能值得分享,以防其他人有类似的问题。最简单的方法是初始化 DataStore 预期接收的结构切片,然后将指向它的指针作为参数 (interface{}) 传递给所需的函数。DataStore,类似于一些解组函数(我尝试过使用 JSON 包)将能够成功地将数据附加到它。尝试在给定特定类型的函数内动态创建切片,然后由函数(例如 DataStore 客户端)接受,这可能非常困难(我还没有设法找到一种方法)。同样,传递一部分接口(以便于迭代)只会使事情复杂化。其次,为了迭代数据(例如将其存储在缓存中),有必要:(1)检索接口的底层值(即指针本身) - 这可以通过使用来实现reflect.ValueOf(pointerInterface),(2)取消引用指针,这样我们就可以访问底层的、可迭代的结构切片——这可以通过调用来完成,(3)使用方法.Elem()迭代底层切片(即使底层类型是可迭代的,也不接受接口)。.Index(i)range自然地,添加一些 switch-case 语句可能适合确保捕获任何错误而不是导致运行时恐慌。因此,以下代码为上述问题提供了一个可行的解决方案:主要:var data []customEntryc.CacheData("Person",&data)以及函数本身:func (cache *MyCache) CacheData(dataQuery string, data interface{}) error {&nbsp; &nbsp; if keys, err := DataStoreClient.GetAll(cache.ctx, datastore.NewQuery(dataQuery), data); err != nil {&nbsp; &nbsp; &nbsp; &nbsp; return err&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; s := reflect.ValueOf(data).Elem()&nbsp; &nbsp; &nbsp; &nbsp; for i := 0; i < s.Len(); i++ {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cache.Set(keys[i].Name, s.Index(i), 1)&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go