Go语言如何实现接收任意切片并返回同类型切片的分页函数?
解决Go中具体类型切片无法传入[]interface{}参数的分页函数问题
问题原因
Go语言中,[]entity.Something 和 []interface{} 是完全不同的类型,无法直接转换。[]interface{} 本质是存储 interface{} 类型元素的切片,每个元素包含类型信息和值的指针;而具体类型切片(如[]entity.Something)是连续存储该类型实例的内存块,两者内存布局不同,因此直接传入会触发编译错误。
解决方案1:使用泛型(Go 1.18+ 推荐)
泛型是处理任意类型切片最简洁且类型安全的方式,无需后续类型断言:
// PaginateSlice 对任意类型切片执行分页操作,返回同类型切片 func PaginateSlice[T any](x []T, page, pageSize int) []T { maxSize := len(x) // 非法参数直接返回空切片 if page < 1 || pageSize < 1 { return []T{} } start := (page - 1) * pageSize // 起始位置超出切片长度,返回空切片 if start >= maxSize { return []T{} } end := start + pageSize // 结束位置超出切片长度,截断到末尾 if end > maxSize { end = maxSize } return x[start:end] }
调用示例:
var result []entity.Something // 直接返回同类型切片,无需类型断言 result = utility.PaginateSlice(dataOfSomethingType, pagination.Page, pagination.PageSize)
解决方案2:使用反射(兼容Go 1.17及以下版本)
如果项目依赖低版本Go,可通过反射实现任意类型切片的分页:
import "reflect" // PaginateSlice 通过反射实现任意类型切片的分页 func PaginateSlice(x interface{}, page, pageSize int) interface{} { v := reflect.ValueOf(x) // 校验输入是否为切片类型 if v.Kind() != reflect.Slice { return nil } maxSize := v.Len() if page < 1 || pageSize < 1 { return reflect.MakeSlice(v.Type(), 0, 0).Interface() } start := (page - 1) * pageSize if start >= maxSize { return reflect.MakeSlice(v.Type(), 0, 0).Interface() } end := start + pageSize if end > maxSize { end = maxSize } return v.Slice(start, end).Interface() }
调用示例:
var result []entity.Something tmp := utility.PaginateSlice(dataOfSomethingType, pagination.Page, pagination.PageSize) // 类型断言转换为目标切片类型 result, ok := tmp.([]entity.Something) if !ok { // 处理类型转换失败的异常情况 }
内容的提问来源于stack exchange,提问作者Mateen Bagheri
相关产品推荐
相关产品推荐

