Go1.23 has brought the range-over-func feature that was an experiment in go1.22 to be used for real. If anyone has read the sample code, you may have to meditate for a long time. bit Don't do that. P'Yod will explain in a very simple way for you to read
Starting from the spec of For statements with range clause, 3 types of Expressions have been added:
func(func() bool) func(func(V) bool) func(func(K, V) bool)
I would like to add one variable to explain as follows
f func(yield func() bool) f func(yield func(V) bool) f func(yield func(K, V) bool)
The spec says that when we use the function f as an expression in rage, every time we call the yield function there before finishing the function f, we get the result in each loop. Equal to the value we inserted into the yield. I'm still confused when I explain it. Better write code
func main() { for range loop { fmt.Println("-") } } func loop(yield func() bool) { yield() yield() }
output:
- -
If we write code like this, we will get 2 complete loops because we call yield 2 times in f according to the spec, here we name it loop and it will not return anything to us. Because we choose to use a pattern with a yield that doesn't accept any arguments
Another example
func main() { for i := range loop { fmt.Println(i) } } func loop(yield func(int) bool) { yield(3) yield(7) }
output:
3 7
This way we will get 2 rounds as well because we call yield once and now range will return 2 values which are 3 and 7 which we use to call yield each time
Another example
func main() { for i := range loop { fmt.Println(i) } } func Loop(yield func(int, string) bool) { yield(3, "three") yield(5, "five") yield(7, "seven") }
output:
3 three 5 five 7 seven
We will get 3 loops and get 2 values per loop according to what we put in the yield each time
And we can also call yield by inserting any type of arguments such as
func loop(yield func(string, bool) bool) { yield("three", true) yield("five", false) yield("seven", false) }
Now that we understand the mechanism of it. When we read difficult examples, we will understand more, such as the example in the Go Wiki: Rangefunc Experiment
package slices func Backward[E any](s []E) func(func(int, E) bool) { return func(yield func(int, E) bool) { for i := len(s)-1; i >= 0; i-- { if !yield(i, s[i]) { return } } } }
main
s := []string{"hello", "world"} for i, x := range slices.Backward(s) { fmt.Println(i, x) }
Much easier to read, right? In the end, how to apply it is up to you. We only look at how many times the yield is called. You will only get it when you put it in range
The value that will come out is the value dropped into the yield. End
Disclaimer: All resources provided are partly from the Internet. If there is any infringement of your copyright or other rights and interests, please explain the detailed reasons and provide proof of copyright or rights and interests and then send it to the email: [email protected] We will handle it for you as soon as possible.
Copyright© 2022 湘ICP备2022001581号-3