创建未知类型的片?

时间:2014-07-16 09:49:29

标签: go couchbase

我尝试使用此功能获取多个值(来自go-couchbase)。

func (b *Bucket) Gets(k string, rv interface{}, caso *uint64) error {
    data, _, cas, err := b.GetsRaw(k)
    if err != nil {
        return err
    }
    if caso != nil {
        *caso = cas
    }
    return json.Unmarshal(data, rv)
}

问题是我不知道如何创建一片rv,因为我不知道它的类型在我的函数中,我不知道它会有多大,所以我可以&# 39;真的通过索引访问rv切片,对吗?

我希望尽可能通用,因此每个rv结构创建一个函数并不是最佳的,而GetBulk函数只返回[]byte

甚至可以做我想做的事情吗?

2 个答案:

答案 0 :(得分:4)

您可以使用reflect包检查类型信息。如果我们有一个具有参数rv interface{}的函数,我们期望传递一个切片的指针,我们可以创建一个引用该切片的reflect.Value

slice := reflect.ValueOf(rv).Elem()

我们可以按如下方式重新初始化切片:

slice.Set(reflect.MakeSlice(slice.Type(), length, capacity))

我们可以使用以下方法确定此切片的元素类型:

elemType := slice.Type().Elem()

然后创建另一个reflect.Value,表示指向新分配的该类型实例的指针:

v := reflect.New(elemType)

现在v.Interface()适合传递给json.Unmarshal这样的函数。填充后,可以将其附加到切片:

slice.Set(reflect.Append(slice, v.Elem()))

有关将一片JSON文档解码为任意切片类型的完整示例,请参阅http://play.golang.org/p/G-SHQO2MAT

答案 1 :(得分:2)

考虑到go-couchbase#Bucket.Gets需要一个界面,您需要将对象放入[]界面,如wiki页面中所述" InterfaceSlice"

var dataSlice []int = foo()
var interfaceSlice []interface{} = make([]interface{}, len(dataSlice))
for i, d := range dataSlice {
    interfaceSlice[i] = d
}

这意味着你已经有了#34;"并且知道它的大小。

或者,既然你想围绕Gets函数"建立一个函数,你可以使用相同的签名,并使用简单的interface{}而不是{{1} }。