我刚开始玩Go。我开始创建一个接受整数数组并返回该数组的块的函数。要明白我的意思,这里是该程序:
package main
import (
"fmt"
"math"
)
func main() {
a:= []int{1,2,3,4,5,6,2, 231, 521,21, 51}
c:=chunks(a[:], 3)
fmt.Println(c) // [[1 2 3] [4 5 6] [2 231 521] [51]]
}
func chunks(a []int, size int) [][]int{
var f float64 = float64(len(a)) / float64(size)
size_of_wrapper := int(math.Ceil(f))
i := 0
j := 0
twoD := make([][]int, size_of_wrapper )
for i < len(a) {
if i + size < len(a) {
twoD[j] = make([]int, size)
twoD[j] = append(a[i:i+size])
i = i + size
j++
} else {
if i + size == len(a){
i++
} else {
twoD[j] = make([]int, 1)
twoD[j] = append(a[len(a)-1:])
i++
}
}
}
return twoD
}
现在,我有一个问题。我是否可以启用此函数以接收包含字符串或任何其他类型的数组?另外,我可以设置最后返回相同类型吗?在这种情况下,我将返回一个仅包含整数值的数组。
我似乎真的很难找到解决这个问题的方法。我读过的其中一篇文章建议将接口类型用于此类工作。那是唯一的吗?
答案 0 :(得分:1)
我可以启用此功能以接收包含字符串或任何其他类型的数组吗? 另外,我可以设置最后返回相同类型吗?我
不幸的是,Go编程语言没有泛型。 AFAIK Go在下一个2.0版本中将具有泛型,因此现在您主要有3个也许是4个选项。
[]interface{}
类型您的函数声明将如下所示。
func chunks(a []interface{}, size int) [][]interface{}
使用这种方法将暗示一些type assertion。
定义将看起来相同,但是这次在您的实现中,而不是使用类型断言技术,您将使用反射包来确定您的类型并检索值。请记住,您将pay a reasonable cost使用这种方法。
您可以使用此通用指针类型,并以C精神进行一些指针运算。
func chunks(a unsafe.Pointer, len uintptr, size uintptr) unsafe.Pointer
我知道,如果您搜索Go并不 正式 ,但是您可以使用以下方法 伪造 这样的技巧。
package main
import "fmt"
import "unsafe"
func main() {
vals := []int{10, 20, 30, 40}
start := unsafe.Pointer(&vals[0])
size := unsafe.Sizeof(int(0))
for i := 0; i < len(vals); i++ {
item := *(*int)(unsafe.Pointer(uintptr(start) + size*uintptr(i)))
fmt.Println(item)
}
}
您可以找到more information,了解如何根据您提供的类型生成go代码。
答案 1 :(得分:1)
因为Go还没有通用名称,所以选项是对每种类型使用反射或重复代码。以下是使用reflect软件包的方法:
// chunkAny slices a into size chunks and puts result in cp.
// The variable cp must be pointer to slice of a's type.
func chunkAny(a interface{}, size int, cp interface{}) {
av := reflect.ValueOf(a)
cv := reflect.ValueOf(cp).Elem()
cv.SetLen(0) // reset length in case backing array allocated
i, j := 0, size
for j < av.Len() {
cv.Set(reflect.Append(cv, av.Slice(i, j)))
i += size
j += size
}
cv.Set(reflect.Append(cv, av.Slice(i, av.Len())))
}
这样调用函数:
a := []string{"a", "b", "c", "d"}
var b [][]string
chunkAny(a, 3, &b)