我有以下代码来加倍切片。
func doubleSlice(s []int) []int {
t := make([]int, len(s), (cap(s) + 1) * 2 )
for i := range s {
t[i] = s[i]
}
return t
}
我想让func加倍任何类型的切片。我需要先了解元素类型。
func showInterfaceItem(s interface{}) interface{} {
if reflect.TypeOf(s).Kind() != reflect.Slice {
fmt.Println("The interface is not a slice.")
return
}
var t interface{}
newLen := reflect.ValueOf(s).Len()
newCap := (cap(reflect.ValueOf(s).Cap()) + 1) * 2
t = make([]reflect.TypeOf(s), newLen, newCap)
return t
}
reflect.TypeOf(s)
返回接口{}的类型,而不是元素的类型。如何获得切片接口的元素类型?
答案 0 :(得分:4)
您可以使用package main
import (
"fmt"
"reflect"
)
func doubleSlice(s interface{}) interface{} {
if reflect.TypeOf(s).Kind() != reflect.Slice {
fmt.Println("The interface is not a slice.")
return nil
}
v := reflect.ValueOf(s)
newLen := v.Len()
newCap := (v.Cap() + 1) * 2
typ := reflect.TypeOf(s).Elem()
t := reflect.MakeSlice(reflect.SliceOf(typ), newLen, newCap)
reflect.Copy(t, v)
return t.Interface()
}
func main() {
xs := doubleSlice([]string{"foo", "bar"}).([]string)
fmt.Println("data =", xs, "len =", len(xs), "cap =", cap(xs))
ys := doubleSlice([]int{3, 1, 4}).([]int)
fmt.Println("data =", ys, "len =", len(ys), "cap =", cap(ys))
}
获得切片元素的类型。
data = [foo bar] len = 2 cap = 6
data = [3 1 4] len = 3 cap = 8
输出将是:
{{1}}
答案 1 :(得分:0)
这在 golang 中是可行的,我花了一整天的时间来发现模式。
首先,我们想得到一个 slice 的指针来让 gorm 开心,它的类型是 "*[]Obj"。为了在 golang 中实现这一点,我们可以像这样创建一个 make 包装器:
func makeWrapper(cap uint) interface{} {
arr:= make([]Sth, 0, cap)
return &arr
}
注意,我们不能直接引用maked的值,这可能是簿记数据需要有一个堆栈空间来存储。
//Not working example
func makeWrapper(cap uint) interface{} {
return &(make([]Sth, 0, cap))
}
和之前的答案一样,reflect.MakeSlice(reflect.SliceOf(typ), 0, capacity).Interface()
返回 interface{[]Sth}
。 (这里的typ
是指reflect.TypeOf(Sth{})
,相当于typ == reflect.TypeOf(v)
)
因此我们需要创建一个*[]Sth
的返回对象,里面的值是一个有容量的切片[]Sth
。理解目标后,我们可以有这样的代码:
package main
import (
"reflect"
)
type Sth struct {
a, b string
}
func main() {
af:= createSlice(Sth{})
arr := makeWrapper(10).(*[]Sth)
println(reflect.TypeOf(arr).String())
// equiv to makeWrapper, but we do it via reflection
arr = af(10).(*[]Sth)
println(reflect.TypeOf(arr).String())
}
func makeWrapper(cap uint) interface{} {
arr:= make([]Sth, 0, cap)
return &arr
}
func createSlice(v interface{}) func(int) interface{} {
var typ reflect.Type
if reflect.ValueOf(v).Kind() == reflect.Ptr {
typ = reflect.ValueOf(v).Elem().Type()
} else if reflect.ValueOf(v).Kind() == reflect.Struct {
typ = reflect.TypeOf(v)
} else {
panic("only support instance of struct or pointer of that instance")
}
return func(capacity int) interface{}{
// create the outer object saves our slice
outerObj:=reflect.New(reflect.SliceOf(typ))
// create the slice and save it to return
outerObj.Elem().Set(reflect.MakeSlice(reflect.SliceOf(typ), 0, capacity))
// retrive the interface of outer object
return outerObj.Interface()
}
}