Repository: go-kratos/kratos (go)

Issue:
v2/config/env watcher stop 后，next 返回值不确定
https://github.com/go-kratos/kratos/blob/80378ca10dc7560c711ccd7a8b22ea0320f0965c/config/env/watcher.go

```
func Test_watcher_Next(t *testing.T) {
	w, err := NewWatcher()
	if err != nil {
		panic(err)
	}
	w.Stop()
	var a, b int
	for i := 0; i < 10000; i++ {
		_, err := w.Next()
		if err == nil {
			a++
		} else {
			b++
		}
	}
	t.Logf("err nil: %v", a)
	t.Logf("err non nil: %v", b)
}
```

```
=== RUN   Test_watcher_Next
    watcher_test.go:22: err nil: 4959
    watcher_test.go:23: err non nil: 5041
--- PASS: Test_watcher_Next (0.00s)
PASS
```

exit 与 cancel 作用貌似重复了，建议去掉一个。
w.cancel() 可以重复执行，close(w.exit) 重复执行会panic

用exit的话，可以改成：
```
case <-w.exit:
	return nil, context.Canceled
```

Pull request description:
chore(config/env): polish watcher
Should fix #1340 

Patch:
diff --git a/config/env/watcher.go b/config/env/watcher.go
index fa7c7682..edcaf3e9 100644
--- a/config/env/watcher.go
+++ b/config/env/watcher.go
@@ -7,8 +7,6 @@ import (
 )
 
 type watcher struct {
-	exit chan struct{}
-
 	ctx    context.Context
 	cancel context.CancelFunc
 }
@@ -17,7 +15,7 @@ var _ config.Watcher = (*watcher)(nil)
 
 func NewWatcher() (config.Watcher, error) {
 	ctx, cancel := context.WithCancel(context.Background())
-	return &watcher{exit: make(chan struct{}), ctx: ctx, cancel: cancel}, nil
+	return &watcher{ctx: ctx, cancel: cancel}, nil
 }
 
 // Next will be blocked until the Stop method is called
@@ -25,13 +23,10 @@ func (w *watcher) Next() ([]*config.KeyValue, error) {
 	select {
 	case <-w.ctx.Done():
 		return nil, w.ctx.Err()
-	case <-w.exit:
-		return nil, nil
 	}
 }
 
 func (w *watcher) Stop() error {
-	close(w.exit)
 	w.cancel()
 	return nil
 }


Test patch:
diff --git a/config/env/watcher_test.go b/config/env/watcher_test.go
new file mode 100644
index 00000000..bea14947
--- /dev/null
+++ b/config/env/watcher_test.go
@@ -0,0 +1,29 @@
+package env
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+)
+
+func Test_watcher_next(t *testing.T) {
+	t.Run("next after stop should return err", func(t *testing.T) {
+		w, err := NewWatcher()
+		require.NoError(t, err)
+
+		_ = w.Stop()
+		_, err = w.Next()
+		assert.Error(t, err)
+	})
+}
+
+func Test_watcher_stop(t *testing.T) {
+	t.Run("stop multiple times should not panic", func(t *testing.T) {
+		w, err := NewWatcher()
+		require.NoError(t, err)
+
+		_ = w.Stop()
+		_ = w.Stop()
+	})
+}