This is an automated email from the ASF dual-hosted git repository.

xuetaoli pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/dubbo-go.git


The following commit(s) were added to refs/heads/develop by this push:
     new 1af833720 feat: update go vesion to 1.24 and remove the use of 
rand.seed (#3046)
1af833720 is described below

commit 1af8337209699ac54f14c9f4bb613e8a69c14368
Author: ian <[email protected]>
AuthorDate: Mon Nov 10 23:11:59 2025 +0800

    feat: update go vesion to 1.24 and remove the use of rand.seed (#3046)
    
    * update the go version and gost version
    
    * fix the random.seed in go1.24
---
 cluster/loadbalance/p2c/loadbalance.go      | 70 ++++++++++++++++++++---------
 cluster/loadbalance/p2c/loadbalance_test.go | 44 +++++++++++++-----
 go.mod                                      |  2 +-
 3 files changed, 83 insertions(+), 33 deletions(-)

diff --git a/cluster/loadbalance/p2c/loadbalance.go 
b/cluster/loadbalance/p2c/loadbalance.go
index 04a4ef648..127d75fc1 100644
--- a/cluster/loadbalance/p2c/loadbalance.go
+++ b/cluster/loadbalance/p2c/loadbalance.go
@@ -37,15 +37,10 @@ import (
        "dubbo.apache.org/dubbo-go/v3/protocol/base"
 )
 
-var (
-       randSeed = func() int64 {
-               return time.Now().Unix()
-       }
-)
-
 func init() {
-       rand.Seed(randSeed())
-       extension.SetLoadbalance(constant.LoadBalanceKeyP2C, newP2CLoadBalance)
+       extension.SetLoadbalance(constant.LoadBalanceKeyP2C, func() 
loadbalance.LoadBalance {
+               return newP2CLoadBalance(nil)
+       })
 }
 
 var (
@@ -53,12 +48,54 @@ var (
        instance loadbalance.LoadBalance
 )
 
-type p2cLoadBalance struct{}
+// p2cLoadBalance is a load balancer implementation based on the Power of Two 
Choices algorithm.
+type p2cLoadBalance struct {
+       // randomPicker is injectable for testing; allows deterministic random 
selection.
+       randomPicker randomPicker
+}
+
+// randomPicker is a function type that randomly selects two distinct indices 
from a range [0, n).
+// This function type is designed ONLY FOR TEST purposes to inject predictable 
values.
+type randomPicker func(n int) (i, j int)
+
+var rndPool = sync.Pool{
+       New: func() any {
+               return rand.New(rand.NewSource(time.Now().Unix()))
+       },
+}
+
+// defaultRnd is the default implementation of randomPicker.
+// It handles edge cases for n <= 2 and ensures two distinct random indices 
for n > 2.
+func defaultRnd(n int) (i, j int) {
+       if n <= 1 {
+               return 0, 0
+       }
+       if n == 2 {
+               return 0, 1
+       }
+
+       rnd := rndPool.Get().(*rand.Rand)
+       defer rndPool.Put(rnd)
 
-func newP2CLoadBalance() loadbalance.LoadBalance {
+       i = rnd.Intn(n) // NOSONAR
+       j = rnd.Intn(n) // NOSONAR
+       for i == j {
+               j = rnd.Intn(n) // NOSONAR
+       }
+       return i, j
+}
+
+// newP2CLoadBalance creates or returns the singleton P2C load balancer.
+// Uses the provided randomPicker if non-nil; otherwise defaults to defaultRnd.
+// randomPicker parameter is designed ONLY FOR TEST purposes.
+// Thread-safe via sync.Once.
+func newP2CLoadBalance(r randomPicker) loadbalance.LoadBalance {
+       if r == nil {
+               r = defaultRnd
+       }
        if instance == nil {
                once.Do(func() {
-                       instance = &p2cLoadBalance{}
+                       instance = &p2cLoadBalance{randomPicker: r}
                })
        }
        return instance
@@ -75,16 +112,7 @@ func (l *p2cLoadBalance) Select(invokers []base.Invoker, 
invocation base.Invocat
        // The local metrics is available only for the earlier version.
        m := metrics.LocalMetrics
        // picks two nodes randomly
-       var i, j int
-       if len(invokers) == 2 {
-               i, j = 0, 1
-       } else {
-               i = rand.Intn(len(invokers))
-               j = i
-               for i == j {
-                       j = rand.Intn(len(invokers))
-               }
-       }
+       i, j := l.randomPicker(len(invokers))
        logger.Debugf("[P2C select] Two invokers were selected, invoker[%d]: 
%s, invoker[%d]: %s.",
                i, invokers[i], j, invokers[j])
 
diff --git a/cluster/loadbalance/p2c/loadbalance_test.go 
b/cluster/loadbalance/p2c/loadbalance_test.go
index 489e0a66e..e8ac720b1 100644
--- a/cluster/loadbalance/p2c/loadbalance_test.go
+++ b/cluster/loadbalance/p2c/loadbalance_test.go
@@ -18,7 +18,6 @@
 package p2c
 
 import (
-       "math/rand"
        "testing"
 )
 
@@ -35,21 +34,48 @@ import (
        protoinvoc "dubbo.apache.org/dubbo-go/v3/protocol/invocation"
 )
 
+func TestDefaultRnd(t *testing.T) {
+       t.Run("n <= 1", func(t *testing.T) {
+               i, j := defaultRnd(1)
+               assert.Equal(t, 0, i)
+               assert.Equal(t, 0, j)
+       })
+
+       t.Run("n == 2", func(t *testing.T) {
+               i, j := defaultRnd(2)
+               assert.Equal(t, 0, i)
+               assert.Equal(t, 1, j)
+       })
+
+       t.Run("n > 2", func(t *testing.T) {
+               n := 5
+               i, j := defaultRnd(n)
+               assert.True(t, i >= 0 && i < n)
+               assert.True(t, j >= 0 && j < n)
+               assert.NotEqual(t, i, j)
+       })
+}
+
 func TestLoadBalance(t *testing.T) {
-       lb := newP2CLoadBalance()
+       // Create P2C load balancer with deterministic randomPicker for 
repeatable tests.
+       // Always returns fixed indices (0,1) except when n <= 1.
+       lb := newP2CLoadBalance(func(n int) (i, j int) {
+               if n <= 1 {
+                       return 0, 0
+               }
+               if n == 2 {
+                       return 0, 1
+               }
+               return 0, 1
+       })
        invocation := protoinvoc.NewRPCInvocation("TestMethod", []any{}, nil)
-       randSeed := func() int64 {
-               return 0
-       }
 
        t.Run("no invokers", func(t *testing.T) {
-               rand.Seed(randSeed())
                ivk := lb.Select([]base.Invoker{}, invocation)
                assert.Nil(t, ivk)
        })
 
        t.Run("one invoker", func(t *testing.T) {
-               rand.Seed(randSeed())
                url0, _ := 
common.NewURL("dubbo://192.168.1.0:20000/com.ikurento.user.UserProvider")
 
                ivkArr := []base.Invoker{
@@ -60,7 +86,6 @@ func TestLoadBalance(t *testing.T) {
        })
 
        t.Run("two invokers", func(t *testing.T) {
-               rand.Seed(randSeed())
                ctrl := gomock.NewController(t)
                defer ctrl.Finish()
 
@@ -90,7 +115,6 @@ func TestLoadBalance(t *testing.T) {
        })
 
        t.Run("multiple invokers", func(t *testing.T) {
-               rand.Seed(randSeed())
                ctrl := gomock.NewController(t)
                defer ctrl.Finish()
 
@@ -122,7 +146,6 @@ func TestLoadBalance(t *testing.T) {
        })
 
        t.Run("metrics i not found", func(t *testing.T) {
-               rand.Seed(randSeed())
                ctrl := gomock.NewController(t)
                defer ctrl.Finish()
 
@@ -150,7 +173,6 @@ func TestLoadBalance(t *testing.T) {
        })
 
        t.Run("metrics j not found", func(t *testing.T) {
-               rand.Seed(randSeed())
                ctrl := gomock.NewController(t)
                defer ctrl.Finish()
 
diff --git a/go.mod b/go.mod
index 724ec6c7a..c1433902c 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
 module dubbo.apache.org/dubbo-go/v3
 
-go 1.23
+go 1.24.0
 
 require (
        github.com/RoaringBitmap/roaring v1.2.3

Reply via email to