目录

Go反射: 将切片按指定大小分块

背景

在写代码过程中,有时候需要做一些批量 查询/操作,往往会涉及将一个很大的数组或切片进行分块。

比如我们有一个存着id的数组,要根据id请求某个接口查询信息,这个接口支持批量查询,但是每次查询的数量上限是100。最好的做法是每次从数组中取最多100个id,进行批量查询,直到遍历完数组。

这个操作不复杂,可以简单的用循环实现,但是每次遇到这种场景都需要写一次代码,有点写吐了。所以就想写一个函数,可以将[]T按需求拆分成[][]T

但是go的泛型还没有来,所以只能用反射来搞了。

献祭我的周六饭后时光

成果

传入[]TT可以是任意类型,按指定大小分块,返回[][]T

例子中将[0,1,2,3,4,5,6,7,8,9]划分成了[0,1,2][3,4,5][6,7,8][9]

https://github.com/kirito41dd/xslice

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
package main

import (
	"fmt"
	"github.com/kirito41dd/xslice"
)

func main() {
	s := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
	i := xslice.SplitToChunks(s, 3)
	ss := i.([][]int)
	fmt.Println(ss) // [[0 1 2] [3 4 5] [6 7 8] [9]]
}

代码实现

反射一把梭,自然离不了可爱的interface{}

欢迎复制或引包github.com/kirito41dd/xslice使用,如果以后搬砖遇到其他场景,也会继续扩充。

还是期待go泛型早点到来(那时候我rust应该已经很6了吧

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
func SplitToChunks(slice interface{}, chunkSize int) interface{} {
	sliceType := reflect.TypeOf(slice)
	sliceVal := reflect.ValueOf(slice)
	length := sliceVal.Len()
	if sliceType.Kind() != reflect.Slice {
		panic("parameter must be []T")
	}
	n := 0
	if length%chunkSize > 0 {
		n = 1
	}
	SST := reflect.MakeSlice(reflect.SliceOf(sliceType), 0, length/chunkSize+n)
	st, ed := 0, 0
	for st < length {
		ed = st + chunkSize
		if ed > length {
			ed = length
		}
		SST = reflect.Append(SST, sliceVal.Slice(st, ed))
		st = ed
	}
	return SST.Interface()
}