我正在学习 Golang,为了好玩,我尝试创建一个 Map 函数,它采用我的 Slice 包装器(其中包含使用 go 1.22 的 GOEXPERIMENT=rangefunc 的 Iter 函数)。但是在 Map 函数中,编译器给了我这个错误:“不能使用 i(int 类型的变量)作为 f 参数中的 T 值”。
type IterableSlice[T any] struct {
slice []T
}
func (is IterableSlice[T]) Iter(yield func(T) bool) {
for _, v := range is.slice {
yield(v)
}
}
func Map[T, V any](is IterableSlice[T], f func(T) V) IterableSlice[V] {
var a []V
for i := range is.slice {
f(i)
}
return IterableSlice[V]{a}
}
func main() {
a := []int{
1, 2, 3, 4, 5,
}
is := IterableSlice[int]{a}
var isf IterableSlice[float32]
isf = Map(is, func(x int) float32 {
return float32(x)
})
for i := range isf.Iter {
fmt.Println(i)
}
}
我正在尝试解决这个错误,或者至少理解这是在 Go 中不可能做到的事情
问题在这里:
for i := range is.slice {
f(i)
}
这里的
i
就是索引。该索引的类型为int
。它无法传递给需要 f
类型值的 T
。
我想你想要的是:
for _, i := range is.slice {
f(i)
}
没检查是否还有其他问题...
Map
函数中的问题是由于尝试将索引(i
)从range
循环传递到函数f
而不是切片中的值而引起的。 range
上的 is.slice
循环会产生索引和值,但在 Map
函数中,您错误地使用了索引。这是更正后的版本:
func Map[T, V any](is IterableSlice[T], f func(T) V) IterableSlice[V] {
var a []V
for _, v := range is.slice {
// Apply the function `f` to each value `v` from the slice, not the index `i`.
a = append(a, f(v))
}
return IterableSlice[V]{a}
}
此外,您在
Iter
函数中使用 main
函数是不正确的。 Iter
方法旨在为切片的每个元素执行提供的函数,而不是直接在 range
语句中使用。正确的用法如下:
func main() {
a := []int{1, 2, 3, 4, 5}
is := IterableSlice[int]{a}
isf := Map(is, func(x int) float32 {
return float32(x)
})
// Properly using the `Iter` method
isf.Iter(func(v float32) bool {
fmt.Println(v)
return true // Indicates to continue the iteration
})
}
在这个更正的方法中,
Iter
函数用于迭代切片isf
中的每个元素,打印每个值。 yield
中的 Iter
函数返回一个布尔值来指示迭代是否应该继续,因此返回 true
确保所有元素都已处理。