From 6802fc555536600b8f0cae60362afe82bc23504b Mon Sep 17 00:00:00 2001 From: amikai Date: Wed, 24 Jul 2024 10:56:30 +0800 Subject: [PATCH] Re-orangize code for compitable - We don't need to use the iter.Seq2 type; instead, we can use func(yield func(int, *Selection) bool). In fact, the underlying type of iter.Seq2 is func(yield func(int, *Selection) bool), so we don't need to upgrade the go.mod version. - For for-range testing in version 1.23, we can use build tags to compile only for versions above 1.23. --- bench_iteration123_test.go | 48 ++++++++++++++++++++++++++++++++++++++ bench_iteration_test.go | 14 +++++------ go.mod | 2 +- iteration.go | 4 +--- iteration123_test.go | 42 +++++++++++++++++++++++++++++++++ iteration_test.go | 22 ++++++++--------- 6 files changed, 109 insertions(+), 23 deletions(-) create mode 100644 bench_iteration123_test.go create mode 100644 iteration123_test.go diff --git a/bench_iteration123_test.go b/bench_iteration123_test.go new file mode 100644 index 0000000..956b723 --- /dev/null +++ b/bench_iteration123_test.go @@ -0,0 +1,48 @@ +//go:build go1.23 +// +build go1.23 + +package goquery + +import "testing" + +func BenchmarkEachIter123(b *testing.B) { + var tmp, n int + + b.StopTimer() + sel := DocW().Find("td") + b.StartTimer() + for i := 0; i < b.N; i++ { + for range sel.EachIter() { + tmp++ + } + if n == 0 { + n = tmp + } + } + if n != 59 { + b.Fatalf("want 59, got %d", n) + } +} + +func BenchmarkEachIterWithBreak123(b *testing.B) { + var tmp, n int + + b.StopTimer() + sel := DocW().Find("td") + b.StartTimer() + for i := 0; i < b.N; i++ { + tmp = 0 + for range sel.EachIter() { + tmp++ + if tmp >= 10 { + break + } + } + if n == 0 { + n = tmp + } + } + if n != 10 { + b.Fatalf("want 10, got %d", n) + } +} diff --git a/bench_iteration_test.go b/bench_iteration_test.go index 1def1a2..1ff9507 100644 --- a/bench_iteration_test.go +++ b/bench_iteration_test.go @@ -32,9 +32,10 @@ func BenchmarkEachIter(b *testing.B) { sel := DocW().Find("td") b.StartTimer() for i := 0; i < b.N; i++ { - for range sel.EachIter() { + sel.EachIter()(func(i int, s *Selection) bool { tmp++ - } + return true + }) if n == 0 { n = tmp } @@ -52,12 +53,11 @@ func BenchmarkEachIterWithBreak(b *testing.B) { b.StartTimer() for i := 0; i < b.N; i++ { tmp = 0 - for range sel.EachIter() { + sel.EachIter()(func(i int, s *Selection) bool { tmp++ - if tmp >= 10 { - break - } - } + return tmp < 10 + }) + if n == 0 { n = tmp } diff --git a/go.mod b/go.mod index 8fba30d..2fe9f3c 100644 --- a/go.mod +++ b/go.mod @@ -5,4 +5,4 @@ require ( golang.org/x/net v0.27.0 ) -go 1.23 +go 1.18 diff --git a/iteration.go b/iteration.go index 1ca5245..882be2d 100644 --- a/iteration.go +++ b/iteration.go @@ -1,7 +1,5 @@ package goquery -import "iter" - // Each iterates over a Selection object, executing a function for each // matched element. It returns the current Selection object. The function // f is called for each element in the selection with the index of the @@ -16,7 +14,7 @@ func (s *Selection) Each(f func(int, *Selection)) *Selection { // EachIter returns an iterator that yields the Selection object in order. // The implementation is similar to Each, but it returns an iterator instead. -func (s *Selection) EachIter() iter.Seq2[int, *Selection] { +func (s *Selection) EachIter() func(yield func(int, *Selection) bool) { return func(yield func(int, *Selection) bool) { for i, n := range s.Nodes { if !yield(i, newSingleSelection(n, s.document)) { diff --git a/iteration123_test.go b/iteration123_test.go new file mode 100644 index 0000000..23f4a2f --- /dev/null +++ b/iteration123_test.go @@ -0,0 +1,42 @@ +//go:build go1.23 +// +build go1.23 + +package goquery + +import "testing" + +func TestEachIter123(t *testing.T) { + var cnt int + + sel := Doc().Find(".hero-unit .row-fluid") + + for i, s := range sel.EachIter() { + cnt++ + t.Logf("At index %v, node %v", i, s.Nodes[0].Data) + } + + sel = sel.Find("a") + + if cnt != 4 { + t.Errorf("Expected EachIter() to call function 4 times, got %v times.", cnt) + } + assertLength(t, sel.Nodes, 6) +} + +func TestEachIterWithBreak123(t *testing.T) { + var cnt int + + sel := Doc().Find(".hero-unit .row-fluid") + for i, s := range sel.EachIter() { + cnt++ + t.Logf("At index %v, node %v", i, s.Nodes[0].Data) + break + } + + sel = sel.Find("a") + + if cnt != 1 { + t.Errorf("Expected EachIter() to call function 1 time, got %v times.", cnt) + } + assertLength(t, sel.Nodes, 6) +} diff --git a/iteration_test.go b/iteration_test.go index 48cebb2..b976fce 100644 --- a/iteration_test.go +++ b/iteration_test.go @@ -110,16 +110,15 @@ func TestEachIter(t *testing.T) { var cnt int sel := Doc().Find(".hero-unit .row-fluid") - - for i, s := range sel.EachIter() { + sel.EachIter()(func(i int, n *Selection) bool { cnt++ - t.Logf("At index %v, node %v", i, s.Nodes[0].Data) - } - + t.Logf("At index %v, node %v", i, n.Nodes[0].Data) + return true + }) sel = sel.Find("a") if cnt != 4 { - t.Errorf("Expected Each() to call function 4 times, got %v times.", cnt) + t.Errorf("Expected EachIter() to call function 4 time, got %v times.", cnt) } assertLength(t, sel.Nodes, 6) } @@ -128,16 +127,15 @@ func TestEachIterWithBreak(t *testing.T) { var cnt int sel := Doc().Find(".hero-unit .row-fluid") - for i, s := range sel.EachIter() { + sel.EachIter()(func(i int, n *Selection) bool { cnt++ - t.Logf("At index %v, node %v", i, s.Nodes[0].Data) - break - } - + t.Logf("At index %v, node %v", i, n.Nodes[0].Data) + return false + }) sel = sel.Find("a") if cnt != 1 { - t.Errorf("Expected Each() to call function 1 time, got %v times.", cnt) + t.Errorf("Expected EachIter() to call function 1 time, got %v times.", cnt) } assertLength(t, sel.Nodes, 6) }