Repository: go-kratos/kratos
Pull request #1598 (2021-11-03 02:26:35)

Modify the README.md of http package. Make the output of gin example consistent with the code.
<!--
🎉 Thanks for sending a pull request to Kratos! Here are some tips for you:

1. If this is your first time contributing to Kratos, please read our contribution guide: https://go-kratos.dev/en/docs/community/contribution/
2. Ensure you have added or ran the appropriate tests and lint for your PR, please use `make lint` and `make test` before filing your PR, use `make clean` to tidy your go mod.
3. If the PR is unfinished, you may need mark it as a WIP(Work In Progress) PR or draft PR
4. Please use a conventional commits format title: `<type>[optional scope]: <description>`
    
    Some suggestion on <type>:

    fix: A bug fix
    feat: A new feature
    test: Adding missing tests or correcting existing tests
    refactor: A code change that neither fixes a bug nor adds a feature
    break: Changes has break change

    docs: Documentation only changes
    deps: Changes external dependencies
    style: Changes that do not affect the meaning of the code (white-space, formatting, etc)
    chore Daily work, examples, etc.
    ci: Changes to our CI configuration files and scripts
-->

#### Description (what this PR does / why we need it):
<!--
* The description should include the motivation for this PR or contrast this with previous behavior
-->


#### Which issue(s) this PR fixes (resolves / be part of):
<!--
* Automatically closes linked issue when PR is merged.
* If you PR is not fully resolved issue, please use `part of #<issue number>` instead.

Usage: `fixes/resolves #<issue number>`, or `fixes/resolves (paste link of issue)`.
-->
fixes #

#### Other special notes for reviewer:
<!--
* Somethings that need extra attention for reviewer
* Some additional notes, TODO list, etc.
-->


codecov-commenter: # [Codecov](https://codecov.io/gh/go-kratos/kratos/pull/1598?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos) Report
> Merging [#1598](https://codecov.io/gh/go-kratos/kratos/pull/1598?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos) (a733b2a) into [main](https://codecov.io/gh/go-kratos/kratos/commit/143dc584cb8aed62d4073232839a243da6678279?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos) (143dc58) will **decrease** coverage by `0.08%`.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/go-kratos/kratos/pull/1598/graphs/tree.svg?width=650&height=150&src=pr&token=XwnmBTz78x&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos)](https://codecov.io/gh/go-kratos/kratos/pull/1598?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos)

```diff
@@            Coverage Diff             @@
##             main    #1598      +/-   ##
==========================================
- Coverage   81.61%   81.52%   -0.09%     
==========================================
  Files          78       78              
  Lines        3389     3389              
==========================================
- Hits         2766     2763       -3     
- Misses        424      426       +2     
- Partials      199      200       +1     
```


| [Impacted Files](https://codecov.io/gh/go-kratos/kratos/pull/1598?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos) | Coverage Δ | |
|---|---|---|
| [selector/node/ewma/node.go](https://codecov.io/gh/go-kratos/kratos/pull/1598/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos#diff-c2VsZWN0b3Ivbm9kZS9ld21hL25vZGUuZ28=) | `85.71% <0.00%> (-3.30%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/go-kratos/kratos/pull/1598?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/go-kratos/kratos/pull/1598?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos). Last update [ce8ed35...a733b2a](https://codecov.io/gh/go-kratos/kratos/pull/1598?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos).


Patch:
diff --git a/contrib/encoding/msgpack/go.sum b/contrib/encoding/msgpack/go.sum
index e0f307f8..e96832c1 100644
--- a/contrib/encoding/msgpack/go.sum
+++ b/contrib/encoding/msgpack/go.sum
@@ -44,7 +44,6 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
 github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
 github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -124,7 +123,6 @@ golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@@ -152,7 +150,6 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
 google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
 google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
diff --git a/contrib/encoding/msgpack/msgpack.go b/contrib/encoding/msgpack/msgpack.go
index e4837dc1..4272b16b 100644
--- a/contrib/encoding/msgpack/msgpack.go
+++ b/contrib/encoding/msgpack/msgpack.go
@@ -1,8 +1,9 @@
 package msgpack
 
 import (
-	"github.com/go-kratos/kratos/v2/encoding"
 	"github.com/vmihailenco/msgpack/v5"
+
+	"github.com/go-kratos/kratos/v2/encoding"
 )
 
 // Name is the name registered for the msgpack compressor.
diff --git a/contrib/registry/kubernetes/registry.go b/contrib/registry/kubernetes/registry.go
index f1e3b95e..16adf076 100644
--- a/contrib/registry/kubernetes/registry.go
+++ b/contrib/registry/kubernetes/registry.go
@@ -12,7 +12,6 @@ import (
 	"strings"
 	"time"
 
-	"github.com/go-kratos/kratos/v2/registry"
 	jsoniter "github.com/json-iterator/go"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -22,6 +21,8 @@ import (
 	"k8s.io/client-go/kubernetes"
 	listerv1 "k8s.io/client-go/listers/core/v1"
 	"k8s.io/client-go/tools/cache"
+
+	"github.com/go-kratos/kratos/v2/registry"
 )
 
 // Defines the key name of specific fields
@@ -166,7 +167,7 @@ func (s *Registry) Service(name string) ([]*registry.ServiceInstance, error) {
 	if err != nil {
 		return nil, err
 	}
-	var ret []*registry.ServiceInstance
+	ret := make([]*registry.ServiceInstance, 0, len(pods))
 	for _, pod := range pods {
 		if pod.Status.Phase != corev1.PodRunning {
 			continue
@@ -342,14 +343,14 @@ func getProtocolMapByEndpoints(endpoints []string) (protocolMap, error) {
 }
 
 func getProtocolMapFromPod(pod *corev1.Pod) (protocolMap, error) {
-	protocolMap := protocolMap{}
+	protoMap := protocolMap{}
 	if s := pod.Annotations[AnnotationsKeyProtocolMap]; !isEmptyObjectString(s) {
-		err := unmarshal(s, &protocolMap)
+		err := unmarshal(s, &protoMap)
 		if err != nil {
 			return nil, &ErrorHandleResource{Namespace: pod.Namespace, Name: pod.Name, Reason: err}
 		}
 	}
-	return protocolMap, nil
+	return protoMap, nil
 }
 
 func getMetadataFromPod(pod *corev1.Pod) (map[string]string, error) {
diff --git a/contrib/registry/nacos/registry.go b/contrib/registry/nacos/registry.go
index f36e4c2f..56414ef7 100644
--- a/contrib/registry/nacos/registry.go
+++ b/contrib/registry/nacos/registry.go
@@ -7,9 +7,10 @@ import (
 	"net/url"
 	"strconv"
 
-	"github.com/go-kratos/kratos/v2/registry"
 	"github.com/nacos-group/nacos-sdk-go/clients/naming_client"
 	"github.com/nacos-group/nacos-sdk-go/vo"
+
+	"github.com/go-kratos/kratos/v2/registry"
 )
 
 var (
@@ -155,7 +156,7 @@ func (r *Registry) GetService(ctx context.Context, serviceName string) ([]*regis
 	if err != nil {
 		return nil, err
 	}
-	var items []*registry.ServiceInstance
+	items := make([]*registry.ServiceInstance, 0, len(res))
 	for _, in := range res {
 		items = append(items, &registry.ServiceInstance{
 			ID:        in.InstanceId,
diff --git a/contrib/registry/nacos/watcher.go b/contrib/registry/nacos/watcher.go
index 9696a864..094505b1 100644
--- a/contrib/registry/nacos/watcher.go
+++ b/contrib/registry/nacos/watcher.go
@@ -4,16 +4,15 @@ import (
 	"context"
 	"fmt"
 
-	"github.com/go-kratos/kratos/v2/registry"
 	"github.com/nacos-group/nacos-sdk-go/clients/naming_client"
 	"github.com/nacos-group/nacos-sdk-go/model"
 	"github.com/nacos-group/nacos-sdk-go/vo"
-)
 
-var (
-	_ registry.Watcher = (*watcher)(nil)
+	"github.com/go-kratos/kratos/v2/registry"
 )
 
+var _ registry.Watcher = (*watcher)(nil)
+
 type watcher struct {
 	serviceName string
 	clusters    []string
@@ -46,36 +45,34 @@ func newWatcher(ctx context.Context, cli naming_client.INamingClient, serviceNam
 }
 
 func (w *watcher) Next() ([]*registry.ServiceInstance, error) {
-	for {
-		select {
-		case <-w.ctx.Done():
-			return nil, w.ctx.Err()
-		case <-w.watchChan:
-		}
-		res, err := w.cli.GetService(vo.GetServiceParam{
-			ServiceName: w.serviceName,
-			GroupName:   w.groupName,
-			Clusters:    w.clusters,
+	select {
+	case <-w.ctx.Done():
+		return nil, w.ctx.Err()
+	case <-w.watchChan:
+	}
+	res, err := w.cli.GetService(vo.GetServiceParam{
+		ServiceName: w.serviceName,
+		GroupName:   w.groupName,
+		Clusters:    w.clusters,
+	})
+	if err != nil {
+		return nil, err
+	}
+	items := make([]*registry.ServiceInstance, 0, len(res.Hosts))
+	for _, in := range res.Hosts {
+		items = append(items, &registry.ServiceInstance{
+			ID:        in.InstanceId,
+			Name:      res.Name,
+			Version:   in.Metadata["version"],
+			Metadata:  in.Metadata,
+			Endpoints: []string{fmt.Sprintf("%s://%s:%d", in.Metadata["kind"], in.Ip, in.Port)},
 		})
-		if err != nil {
-			return nil, err
-		}
-		var items []*registry.ServiceInstance
-		for _, in := range res.Hosts {
-			items = append(items, &registry.ServiceInstance{
-				ID:        in.InstanceId,
-				Name:      res.Name,
-				Version:   in.Metadata["version"],
-				Metadata:  in.Metadata,
-				Endpoints: []string{fmt.Sprintf("%s://%s:%d", in.Metadata["kind"], in.Ip, in.Port)},
-			})
-		}
-		return items, nil
 	}
+	return items, nil
 }
 
 func (w *watcher) Stop() error {
 	w.cancel()
-	//close
+	// close
 	return nil
 }
diff --git a/contrib/registry/zookeeper/register.go b/contrib/registry/zookeeper/register.go
index 22062bb0..3f73e64f 100644
--- a/contrib/registry/zookeeper/register.go
+++ b/contrib/registry/zookeeper/register.go
@@ -8,8 +8,9 @@ import (
 	"sync/atomic"
 	"time"
 
-	"github.com/go-kratos/kratos/v2/registry"
 	"github.com/go-zookeeper/zk"
+
+	"github.com/go-kratos/kratos/v2/registry"
 )
 
 var (
@@ -70,9 +71,11 @@ func New(zkServers []string, opts ...Option) (*Registry, error) {
 }
 
 func (r *Registry) Register(ctx context.Context, service *registry.ServiceInstance) error {
-	var data []byte
-	var err error
-	if err := r.ensureName(r.opts.rootPath, []byte("")); err != nil {
+	var (
+		data []byte
+		err  error
+	)
+	if err = r.ensureName(r.opts.rootPath, []byte("")); err != nil {
 		return err
 	}
 	serviceNamePath := path.Join(r.opts.rootPath, service.Name)
@@ -113,9 +116,9 @@ func (r *Registry) GetService(ctx context.Context, serviceName string) ([]*regis
 	if err != nil {
 		return nil, err
 	}
-	var items []*registry.ServiceInstance
+	items := make([]*registry.ServiceInstance, 0, len(servicesID))
 	for _, service := range servicesID {
-		var item = &registry.ServiceInstance{}
+		item := &registry.ServiceInstance{}
 		servicePath := path.Join(serviceNamePath, service)
 		serviceInstanceByte, _, err := r.conn.Get(servicePath)
 		if err != nil {
@@ -135,7 +138,7 @@ func (r *Registry) Watch(ctx context.Context, serviceName string) (registry.Watc
 	set, ok := r.registry[serviceName]
 	if !ok {
 		set = &serviceSet{
-			watcher:     make(map[*watcher]struct{}, 0),
+			watcher:     make(map[*watcher]struct{}),
 			services:    &atomic.Value{},
 			serviceName: serviceName,
 		}
diff --git a/contrib/registry/zookeeper/watcher.go b/contrib/registry/zookeeper/watcher.go
index 9430e9ce..c56f3d08 100644
--- a/contrib/registry/zookeeper/watcher.go
+++ b/contrib/registry/zookeeper/watcher.go
@@ -6,9 +6,7 @@ import (
 	"github.com/go-kratos/kratos/v2/registry"
 )
 
-var (
-	_ registry.Watcher = &watcher{}
-)
+var _ registry.Watcher = &watcher{}
 
 type watcher struct {
 	ctx    context.Context
@@ -25,9 +23,7 @@ func (w watcher) Next() (services []*registry.ServiceInstance, err error) {
 	}
 	ss, ok := w.set.services.Load().([]*registry.ServiceInstance)
 	if ok {
-		for _, s := range ss {
-			services = append(services, s)
-		}
+		services = append(services, ss...)
 	}
 	return
 }
diff --git a/examples/go.sum b/examples/go.sum
index a87f760e..742d10b3 100644
--- a/examples/go.sum
+++ b/examples/go.sum
@@ -748,7 +748,6 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
 golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
 golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
 golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
diff --git a/examples/http/README.md b/examples/http/README.md
index 1c2df553..120b8c86 100644
--- a/examples/http/README.md
+++ b/examples/http/README.md
@@ -7,8 +7,8 @@ $ go run gin/main.go
 ```
 2、From a different terminal, access the api to see the output:
 ```shell
-$ curl http://127.0.0.1:8000/home
-Hello Gin!
+$ curl http://127.0.0.1:8000/helloworld/gin
+{"welcome":"gin"}
 ```
 
 ## mux
@@ -30,4 +30,4 @@ $ go run static/main.go
 2、Access the following url with your browser:
 ```
 http://127.0.0.1:8000/assets
-```
\ No newline at end of file
+```
diff --git a/hack/.lintcheck_failures b/hack/.lintcheck_failures
index 80388962..8b137891 100644
--- a/hack/.lintcheck_failures
+++ b/hack/.lintcheck_failures
@@ -1,3 +1,1 @@
-./contrib/registry/nacos
-./contrib/registry/kubernetes
-./contrib/registry/zookeeper
+
diff --git a/middleware/recovery/recovery.go b/middleware/recovery/recovery.go
index 94f3eb54..4637bf02 100644
--- a/middleware/recovery/recovery.go
+++ b/middleware/recovery/recovery.go
@@ -56,7 +56,7 @@ func Recovery(opts ...Option) middleware.Middleware {
 					buf := make([]byte, 64<<10) //nolint:gomnd
 					n := runtime.Stack(buf, false)
 					buf = buf[:n]
-					logger.Errorf("%v: %+v\n%s\n", rerr, req, buf)
+					logger.WithContext(ctx).Errorf("%v: %+v\n%s\n", rerr, req, buf)
 
 					err = op.handler(ctx, req, rerr)
 				}
diff --git a/selector/node/direct/direct.go b/selector/node/direct/direct.go
index 9e409849..e3bf139d 100644
--- a/selector/node/direct/direct.go
+++ b/selector/node/direct/direct.go
@@ -13,12 +13,12 @@ const (
 )
 
 var (
-	_ selector.WeightedNode        = &node{}
+	_ selector.WeightedNode        = &Node{}
 	_ selector.WeightedNodeBuilder = &Builder{}
 )
 
-// node is endpoint instance
-type node struct {
+// Node is endpoint instance
+type Node struct {
 	selector.Node
 
 	// last lastPick timestamp
@@ -30,23 +30,23 @@ type Builder struct{}
 
 // Build create node
 func (*Builder) Build(n selector.Node) selector.WeightedNode {
-	return &node{Node: n, lastPick: 0}
+	return &Node{Node: n, lastPick: 0}
 }
 
-func (n *node) Pick() selector.DoneFunc {
+func (n *Node) Pick() selector.DoneFunc {
 	now := time.Now().UnixNano()
 	atomic.StoreInt64(&n.lastPick, now)
 	return func(ctx context.Context, di selector.DoneInfo) {}
 }
 
 // Weight is node effective weight
-func (n *node) Weight() float64 {
+func (n *Node) Weight() float64 {
 	if n.InitialWeight() != nil {
 		return float64(*n.InitialWeight())
 	}
 	return defaultWeight
 }
 
-func (n *node) PickElapsed() time.Duration {
+func (n *Node) PickElapsed() time.Duration {
 	return time.Duration(time.Now().UnixNano() - atomic.LoadInt64(&n.lastPick))
 }
diff --git a/selector/node/ewma/node.go b/selector/node/ewma/node.go
index 06b37178..444d8018 100644
--- a/selector/node/ewma/node.go
+++ b/selector/node/ewma/node.go
@@ -20,12 +20,12 @@ const (
 )
 
 var (
-	_ selector.WeightedNode        = &node{}
+	_ selector.WeightedNode        = &Node{}
 	_ selector.WeightedNodeBuilder = &Builder{}
 )
 
-// node is endpoint instance
-type node struct {
+// Node is endpoint instance
+type Node struct {
 	selector.Node
 
 	// client statistic data
@@ -53,7 +53,7 @@ type Builder struct {
 
 // Build create a weighted node.
 func (b *Builder) Build(n selector.Node) selector.WeightedNode {
-	s := &node{
+	s := &Node{
 		Node:       n,
 		lag:        0,
 		success:    1000,
@@ -64,11 +64,11 @@ func (b *Builder) Build(n selector.Node) selector.WeightedNode {
 	return s
 }
 
-func (n *node) health() uint64 {
+func (n *Node) health() uint64 {
 	return atomic.LoadUint64(&n.success)
 }
 
-func (n *node) load() (load uint64) {
+func (n *Node) load() (load uint64) {
 	now := time.Now().UnixNano()
 	avgLag := atomic.LoadInt64(&n.lag)
 	lastPredictTs := atomic.LoadInt64(&n.predictTs)
@@ -117,7 +117,7 @@ func (n *node) load() (load uint64) {
 }
 
 // Pick pick a node.
-func (n *node) Pick() selector.DoneFunc {
+func (n *Node) Pick() selector.DoneFunc {
 	now := time.Now().UnixNano()
 	atomic.StoreInt64(&n.lastPick, now)
 	atomic.AddInt64(&n.inflight, 1)
@@ -170,11 +170,11 @@ func (n *node) Pick() selector.DoneFunc {
 }
 
 // Weight is node effective weight.
-func (n *node) Weight() (weight float64) {
+func (n *Node) Weight() (weight float64) {
 	weight = float64(n.health()*uint64(time.Second)) / float64(n.load())
 	return
 }
 
-func (n *node) PickElapsed() time.Duration {
+func (n *Node) PickElapsed() time.Duration {
 	return time.Duration(time.Now().UnixNano() - atomic.LoadInt64(&n.lastPick))
 }


Test patch:
diff --git a/contrib/registry/zookeeper/register_test.go b/contrib/registry/zookeeper/register_test.go
index 6e2f92c7..f746b104 100644
--- a/contrib/registry/zookeeper/register_test.go
+++ b/contrib/registry/zookeeper/register_test.go
@@ -22,11 +22,13 @@ func TestRegistry(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	defer w.Stop()
+	defer func() {
+		_ = w.Stop()
+	}()
 	go func() {
 		for {
-			res, err := w.Next()
-			if err != nil {
+			res, nextErr := w.Next()
+			if nextErr != nil {
 				return
 			}
 			t.Logf("watch: %d", len(res))
@@ -37,7 +39,7 @@ func TestRegistry(t *testing.T) {
 	}()
 	time.Sleep(time.Second)
 
-	if err := r.Register(ctx, s); err != nil {
+	if err = r.Register(ctx, s); err != nil {
 		t.Fatal(err)
 	}
 	time.Sleep(time.Second)
@@ -53,7 +55,7 @@ func TestRegistry(t *testing.T) {
 		t.Errorf("not expected: %+v", res)
 	}
 
-	if err := r.Deregister(ctx, s); err != nil {
+	if err = r.Deregister(ctx, s); err != nil {
 		t.Fatal(err)
 	}
 	time.Sleep(time.Second)
diff --git a/selector/p2c/p2c_test.go b/selector/p2c/p2c_test.go
index 747345a1..32db03b7 100644
--- a/selector/p2c/p2c_test.go
+++ b/selector/p2c/p2c_test.go
@@ -56,12 +56,12 @@ func TestWrr3(t *testing.T) {
 		}()
 	}
 	group.Wait()
-	assert.Greater(t, count1, int64(2000))
-	assert.Less(t, count1, int64(4000))
-	assert.Greater(t, count2, int64(2000))
-	assert.Less(t, count2, int64(4000))
-	assert.Greater(t, count3, int64(2000))
-	assert.Less(t, count3, int64(4000))
+	assert.Greater(t, count1, int64(1500))
+	assert.Less(t, count1, int64(4500))
+	assert.Greater(t, count2, int64(1500))
+	assert.Less(t, count2, int64(4500))
+	assert.Greater(t, count3, int64(1500))
+	assert.Less(t, count3, int64(4500))
 }
 
 func TestEmpty(t *testing.T) {