简体   繁体   English

如何对作为切片的接口{}进行子切片?

[英]How to sub slice an interface{} that is a slice?

The datastore.GetMulti(c appengine.Context, key []*Key, dst interface{}) API allows me to get 1000 entities at most. datastore.GetMulti(c appengine.Context, key []*Key, dst interface{}) API允许我最多获得1000个实体。 I want to get more. 我想得到更多。

An obvious way to solve this generically is to create a wrapper function mypkg.GetMulti() which sub slices ( key[0:1000], key[1000:2000]... ) the original arguments and calls datastore.GetMulti() several times with them. 一般来说解决这个问题的一个明显方法是创建一个包装函数mypkg.GetMulti() ,其子切片( key[0:1000], key[1000:2000]... )原始参数并调用datastore.GetMulti()几个和他们在一起。

It's pretty clear how to sub slice key []*Key , but how do I sub slice dst interface{} which could be: 很清楚如何分切片key []*Key ,但我如何分切片dst interface{}可能是:

// dst must be a []S, []*S, []I or []P, for some struct type S, some interface
// type I, or some non-interface non-pointer type P such that P or *P
// implements PropertyLoadSaver. If an []I, each element must be a valid dst
// for Get: it must be a struct pointer or implement PropertyLoadSaver.
//
// As a special case, PropertyList is an invalid type for dst, even though a
// PropertyList is a slice of structs. It is treated as invalid to avoid being
// mistakenly passed when []PropertyList was intended.

Since you are the caller of datastore.GetMulti which takes an interface{} argument, you can provide any concrete value as that argument; 由于您是采用interface{}参数的datastore.GetMulti的调用者,因此您可以提供任何具体值作为该参数; it doesn't need to be converted to the empty-interface type beforehand. 它不需要事先转换为空接口类型。 In other words, anything and everything implements the empty interface, so just pass that thing. 换句话说,任何东西都可以实现空接口,所以只需传递那个东西。

func GetMulti() {
    mySlice := make([]Whatever, 3000, 3000)
    for i := 0; i < 3; i++ {
        subSlice := mySlice[i * 1000 : (i + 1) * 1000]
        datastore.GetMulti(c,k, subSlice) // 'c' and 'k' assumed to be defined
    }
}

In case mypkg.GetMulti should be a generic function, taking an interface{} value as well, then you'll have to use reflection as in the following example where instead of fmt.Println with the length of the subslice you'd call datastore.GetMulti with each subslice: 如果mypkg.GetMulti应该是一个泛型函数,同样取一个interface{}值,那么你将不得不使用反射,如下例所示 ,而不是fmt.Println ,而你的fmt.Println长度你称之为datastore.GetMulti与每个子datastore.GetMulti

package main

import "fmt"
import "reflect"

func GetMulti(i interface{}) {
    v := reflect.ValueOf(i)
    if v.Kind() != reflect.Slice {
        panic("argument not a slice")
    }
    l := v.Len()
    p := (l / 1000)
    for i := 0; i < p; i++ {
        fmt.Println(v.Slice(i*1000, (i+1)*1000).Len())
    }
    fmt.Println(v.Slice(p*1000, l).Len())

}

func main() {
    s := make([]int, 3560, 3560)
    GetMulti(s)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM