Golang中使用闭包返回泛型的实现方法
Golang中使用闭包返回泛型的实现方法
package main
import "fmt"
func chunker[T any]() func([]T, int) [][]T {
return func(ar []T, size int) [][]T {
var finalAr [][]T
for i := 0; i < len(ar); i += size {
end := i + size
if end > len(ar) {
end = len(ar)
}
finalAr = append(finalAr, ar[i:end])
}
return finalAr
}
}
func main() {
xI := []int{1, 2, 3, 0, 0, 5, 6, 4, 7, 8, 9, 10}
fmt.Println(chunker()(xI, 3))
}
这会抛出错误:
./prog.go:20:21: cannot infer T (prog.go:5:14)
其不使用闭包返回的等效代码可以正常工作:
package main
import "fmt"
func chunker[T any](ar []T, size int) [][]T {
var finalAr [][]T
for i := 0; i < len(ar); i += size {
end := i + size
if end > len(ar) {
end = len(ar)
}
finalAr = append(finalAr, ar[i:end])
}
return finalAr
}
func main() {
xI := []int{1, 2, 3, 0, 0, 5, 6, 4, 7, 8, 9, 10}
xS := []string{"a", "b", "c", "c", "d", "e", "f", "g", "h"}
fmt.Println(chunker(xI, 3))
fmt.Println(chunker(xS, 4))
}
输出如下:
[[1 2 3] [0 0 5] [6 4 7] [8 9 10]] [[a b c c] [d e f g] [h]]
这是预期的结果。
如何让闭包版本正常工作?
更多关于Golang中使用闭包返回泛型的实现方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html
这个问题的答案非常简单,你需要明确地将切片的基础类型传递给函数。只需将 chunker()(xI, 3) 改为 chunker[int]()(xI, 3)。这样编译器就能理解你试图用泛型处理哪种类型的数据,而不会报错。
更多关于Golang中使用闭包返回泛型的实现方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
我认为你在这里能做的很有限。由于你将 i 定义为循环计数器,其类型是 int。你需要确保 size 变量也是数值类型。如果你想让它变得通用(但我不推荐),你需要在闭包内部进行类型断言,类似这样:
var sizeInt = any(size).(int)
for i := 0; i < len(ar); i += sizeInt {
但正如我上面所说,这不是一个好方法,因为一旦你传入无法断言为整数的内容,你的函数就会发生恐慌。size 总是某种数值类型,可以像现在这样保持为 int。例如,你可以查看 Go 中新的 slices 包,他们在其中添加了泛型函数来处理不同类型的切片。特别是 Delete 函数,所有请求的切片边界都是 int 类型。
感谢回复,它终于可以工作了。
当 size 参数的类型是泛型 T 而不是 int 时,我应该怎么做才能让它正常工作?
如果我把 int 换成 T,它会抛出以下错误:
./prog.go:8:28: 无效操作: i += size (类型 int 和 T 不匹配) ./prog.go:9:11: 无效操作: i + size (类型 int 和 T 不匹配)
package main
import "fmt"
func chunker[T any]() func([]T, T) [][]T {
return func(ar []T, size T) [][]T {
var finalAr [][]T
for i := 0; i < len(ar); i += size {
end := i + size
if end > len(ar) {
end = len(ar)
}
finalAr = append(finalAr, ar[i:end])
}
return finalAr
}
}
func main() {
xI := []int{1, 2, 3, 0, 0, 5, 6, 4, 7, 8, 9, 10}
fmt.Println(chunker[int]()(xI, 3))
}
在Go中,当泛型函数返回闭包时,编译器无法从外部调用自动推断类型参数。你需要显式指定类型参数。以下是修复后的代码:
package main
import "fmt"
func chunker[T any]() func([]T, int) [][]T {
return func(ar []T, size int) [][]T {
var finalAr [][]T
for i := 0; i < len(ar); i += size {
end := i + size
if end > len(ar) {
end = len(ar)
}
finalAr = append(finalAr, ar[i:end])
}
return finalAr
}
}
func main() {
xI := []int{1, 2, 3, 0, 0, 5, 6, 4, 7, 8, 9, 10}
// 显式指定类型参数
chunkInts := chunker[int]()
fmt.Println(chunkInts(xI, 3))
// 或者直接调用时指定类型
fmt.Println(chunker[int]()(xI, 3))
// 字符串示例
xS := []string{"a", "b", "c", "c", "d", "e", "f", "g", "h"}
chunkStrings := chunker[string]()
fmt.Println(chunkStrings(xS, 4))
}
输出:
[[1 2 3] [0 0 5] [6 4 7] [8 9 10]]
[[1 2 3] [0 0 5] [6 4 7] [8 9 10]]
[[a b c c] [d e f g] [h]]
关键点是:当调用返回闭包的泛型函数时,编译器无法从后续的闭包调用中反向推断类型参数,因此必须显式指定类型参数 chunker[int]() 或 chunker[string]()。

