style(config): code style tweaks and abstracts some methods (#2465)

* style(config): code specification tweaks and abstracts some methods

* optimize

* modify func location
pull/2484/head
jessetang 2 years ago committed by GitHub
parent 03d9494b19
commit 2a65502be2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 14
      config/config.go
  2. 41
      config/config_test.go
  3. 6
      config/env/env.go
  4. 4
      config/env/watcher.go
  5. 14
      config/file/file_test.go
  6. 4
      config/file/format_test.go
  7. 4
      config/file/watcher.go
  8. 14
      config/options_test.go
  9. 20
      config/reader.go
  10. 46
      config/reader_test.go
  11. 64
      config/value.go
  12. 71
      config/value_test.go
  13. 5
      contrib/metrics/datadog/go.mod

@ -15,13 +15,13 @@ import (
"github.com/go-kratos/kratos/v2/log" "github.com/go-kratos/kratos/v2/log"
) )
var _ Config = (*config)(nil)
var ( var (
// ErrNotFound is key not found. // ErrNotFound is key not found.
ErrNotFound = errors.New("key not found") ErrNotFound = errors.New("key not found")
// ErrTypeAssert is type assert error. // ErrTypeAssert is type assert error.
ErrTypeAssert = errors.New("type assert error") ErrTypeAssert = errors.New("type assert error")
_ Config = (*config)(nil)
) )
// Observer is config observer. // Observer is config observer.
@ -44,7 +44,7 @@ type config struct {
watchers []Watcher watchers []Watcher
} }
// New new a config with options. // New a config with options.
func New(opts ...Option) Config { func New(opts ...Option) Config {
o := options{ o := options{
decoder: defaultDecoder, decoder: defaultDecoder,
@ -62,11 +62,11 @@ func New(opts ...Option) Config {
func (c *config) watch(w Watcher) { func (c *config) watch(w Watcher) {
for { for {
kvs, err := w.Next() kvs, err := w.Next()
if errors.Is(err, context.Canceled) {
log.Infof("watcher's ctx cancel : %v", err)
return
}
if err != nil { if err != nil {
if errors.Is(err, context.Canceled) {
log.Infof("watcher's ctx cancel : %v", err)
return
}
time.Sleep(time.Second) time.Sleep(time.Second)
log.Errorf("failed to watch next config: %v", err) log.Errorf("failed to watch next config: %v", err)
continue continue

@ -2,7 +2,6 @@ package config
import ( import (
"errors" "errors"
"reflect"
"testing" "testing"
) )
@ -124,7 +123,7 @@ func TestConfig(t *testing.T) {
) )
err = c.Close() err = c.Close()
if err != nil { if err != nil {
t.Fatal("t is not nil") t.Fatal(err)
} }
jSource := newTestJSONSource(_testJSON) jSource := newTestJSONSource(_testJSON)
@ -139,21 +138,21 @@ func TestConfig(t *testing.T) {
err = cf.Load() err = cf.Load()
if err != nil { if err != nil {
t.Fatal("t is not nil") t.Fatal(err)
} }
val, err := cf.Value("data.database.driver").String() driver, err := cf.Value("data.database.driver").String()
if err != nil { if err != nil {
t.Fatal("t is not nil") t.Fatal(err)
} }
if !reflect.DeepEqual(databaseDriver, val) { if databaseDriver != driver {
t.Fatal(`databaseDriver is not equal to val`) t.Fatal("databaseDriver is not equal to val")
} }
err = cf.Watch("endpoints", func(key string, value Value) { err = cf.Watch("endpoints", func(key string, value Value) {
}) })
if err != nil { if err != nil {
t.Fatal("t is not nil") t.Fatal(err)
} }
jSource.sig <- struct{}{} jSource.sig <- struct{}{}
@ -162,24 +161,24 @@ func TestConfig(t *testing.T) {
var testConf testConfigStruct var testConf testConfigStruct
err = cf.Scan(&testConf) err = cf.Scan(&testConf)
if err != nil { if err != nil {
t.Fatal("t is not nil") t.Fatal(err)
} }
if !reflect.DeepEqual(httpAddr, testConf.Server.HTTP.Addr) { if httpAddr != testConf.Server.HTTP.Addr {
t.Fatal(`httpAddr is not equal to testConf.Server.HTTP.Addr`) t.Errorf("testConf.Server.HTTP.Addr want: %s, got: %s", httpAddr, testConf.Server.HTTP.Addr)
} }
if !reflect.DeepEqual(httpTimeout, testConf.Server.HTTP.Timeout) { if httpTimeout != testConf.Server.HTTP.Timeout {
t.Fatal(`httpTimeout is not equal to testConf.Server.HTTP.Timeout`) t.Errorf("testConf.Server.HTTP.Timeout want: %.1f, got: %.1f", httpTimeout, testConf.Server.HTTP.Timeout)
} }
if !reflect.DeepEqual(true, testConf.Server.HTTP.EnableSSL) { if !testConf.Server.HTTP.EnableSSL {
t.Fatal(`testConf.Server.HTTP.EnableSSL is not equal to true`) t.Error("testConf.Server.HTTP.EnableSSL is not equal to true")
} }
if !reflect.DeepEqual(grpcPort, testConf.Server.GRPC.Port) { if grpcPort != testConf.Server.GRPC.Port {
t.Fatal(`grpcPort is not equal to testConf.Server.GRPC.Port`) t.Errorf("testConf.Server.GRPC.Port want: %d, got: %d", grpcPort, testConf.Server.GRPC.Port)
} }
if !reflect.DeepEqual(endpoint1, testConf.Endpoints[0]) { if endpoint1 != testConf.Endpoints[0] {
t.Fatal(`endpoint1 is not equal to testConf.Endpoints[0]`) t.Errorf("testConf.Endpoints[0] want: %s, got: %s", endpoint1, testConf.Endpoints[0])
} }
if !reflect.DeepEqual(len(testConf.Endpoints), 2) { if len(testConf.Endpoints) != 2 {
t.Fatal(`len(testConf.Endpoints) is not equal to 2`) t.Error("len(testConf.Endpoints) is not equal to 2")
} }
} }

6
config/env/env.go vendored

@ -19,11 +19,11 @@ func (e *env) Load() (kv []*config.KeyValue, err error) {
return e.load(os.Environ()), nil return e.load(os.Environ()), nil
} }
func (e *env) load(envStrings []string) []*config.KeyValue { func (e *env) load(envs []string) []*config.KeyValue {
var kv []*config.KeyValue var kv []*config.KeyValue
for _, envstr := range envStrings { for _, env := range envs {
var k, v string var k, v string
subs := strings.SplitN(envstr, "=", 2) //nolint:gomnd subs := strings.SplitN(env, "=", 2) //nolint:gomnd
k = subs[0] k = subs[0]
if len(subs) > 1 { if len(subs) > 1 {
v = subs[1] v = subs[1]

@ -6,13 +6,13 @@ import (
"github.com/go-kratos/kratos/v2/config" "github.com/go-kratos/kratos/v2/config"
) )
var _ config.Watcher = (*watcher)(nil)
type watcher struct { type watcher struct {
ctx context.Context ctx context.Context
cancel context.CancelFunc cancel context.CancelFunc
} }
var _ config.Watcher = (*watcher)(nil)
func NewWatcher() (config.Watcher, error) { func NewWatcher() (config.Watcher, error) {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
return &watcher{ctx: ctx, cancel: cancel}, nil return &watcher{ctx: ctx, cancel: cancel}, nil

@ -121,10 +121,10 @@ func testWatchFile(t *testing.T, path string) {
} }
kvs, err := watch.Next() kvs, err := watch.Next()
if err != nil { if err != nil {
t.Errorf(`watch.Next() error(%v)`, err) t.Errorf("watch.Next() error(%v)", err)
} }
if !reflect.DeepEqual(string(kvs[0].Value), _testJSONUpdate) { if !reflect.DeepEqual(string(kvs[0].Value), _testJSONUpdate) {
t.Errorf(`string(kvs[0].Value(%v) is not equal to _testJSONUpdate(%v)`, kvs[0].Value, _testJSONUpdate) t.Errorf("string(kvs[0].Value(%v) is not equal to _testJSONUpdate(%v)", kvs[0].Value, _testJSONUpdate)
} }
newFilepath := filepath.Join(filepath.Dir(path), "test1.json") newFilepath := filepath.Join(filepath.Dir(path), "test1.json")
@ -133,15 +133,15 @@ func testWatchFile(t *testing.T, path string) {
} }
kvs, err = watch.Next() kvs, err = watch.Next()
if err == nil { if err == nil {
t.Errorf(`watch.Next() error(%v)`, err) t.Errorf("watch.Next() error(%v)", err)
} }
if kvs != nil { if kvs != nil {
t.Errorf(`watch.Next() error(%v)`, err) t.Errorf("watch.Next() error(%v)", err)
} }
err = watch.Stop() err = watch.Stop()
if err != nil { if err != nil {
t.Errorf(`watch.Stop() error(%v)`, err) t.Errorf("watch.Stop() error(%v)", err)
} }
if err := os.Rename(newFilepath, path); err != nil { if err := os.Rename(newFilepath, path); err != nil {
@ -171,10 +171,10 @@ func testWatchDir(t *testing.T, path, file string) {
kvs, err := watch.Next() kvs, err := watch.Next()
if err != nil { if err != nil {
t.Errorf(`watch.Next() error(%v)`, err) t.Errorf("watch.Next() error(%v)", err)
} }
if !reflect.DeepEqual(string(kvs[0].Value), _testJSONUpdate) { if !reflect.DeepEqual(string(kvs[0].Value), _testJSONUpdate) {
t.Errorf(`string(kvs[0].Value(%v) is not equal to _testJSONUpdate(%v)`, kvs[0].Value, _testJSONUpdate) t.Errorf("string(kvs[0].Value(%s) is not equal to _testJSONUpdate(%v)", kvs[0].Value, _testJSONUpdate)
} }
} }

@ -1,6 +1,8 @@
package file package file
import "testing" import (
"testing"
)
func TestFormat(t *testing.T) { func TestFormat(t *testing.T) {
tests := []struct { tests := []struct {

@ -10,6 +10,8 @@ import (
"github.com/go-kratos/kratos/v2/config" "github.com/go-kratos/kratos/v2/config"
) )
var _ config.Watcher = (*watcher)(nil)
type watcher struct { type watcher struct {
f *file f *file
fw *fsnotify.Watcher fw *fsnotify.Watcher
@ -18,8 +20,6 @@ type watcher struct {
cancel context.CancelFunc cancel context.CancelFunc
} }
var _ config.Watcher = (*watcher)(nil)
func newWatcher(f *file) (config.Watcher, error) { func newWatcher(f *file) (config.Watcher, error) {
fw, err := fsnotify.NewWatcher() fw, err := fsnotify.NewWatcher()
if err != nil { if err != nil {

@ -15,7 +15,7 @@ func TestDefaultDecoder(t *testing.T) {
target := make(map[string]interface{}) target := make(map[string]interface{})
err := defaultDecoder(src, target) err := defaultDecoder(src, target)
if err != nil { if err != nil {
t.Fatal("err is not nil") t.Fatal(err)
} }
if !reflect.DeepEqual(target, map[string]interface{}{"service": []byte("config")}) { if !reflect.DeepEqual(target, map[string]interface{}{"service": []byte("config")}) {
t.Fatal(`target is not equal to map[string]interface{}{"service": "config"}`) t.Fatal(`target is not equal to map[string]interface{}{"service": "config"}`)
@ -29,7 +29,7 @@ func TestDefaultDecoder(t *testing.T) {
target = make(map[string]interface{}) target = make(map[string]interface{})
err = defaultDecoder(src, target) err = defaultDecoder(src, target)
if err != nil { if err != nil {
t.Fatal("err is not nil") t.Fatal(err)
} }
if !reflect.DeepEqual(map[string]interface{}{ if !reflect.DeepEqual(map[string]interface{}{
"service": map[string]interface{}{ "service": map[string]interface{}{
@ -150,7 +150,7 @@ func TestDefaultResolver(t *testing.T) {
t.Run(test.name, func(t *testing.T) { t.Run(test.name, func(t *testing.T) {
err := defaultResolver(data) err := defaultResolver(data)
if err != nil { if err != nil {
t.Fatal(`err is not nil`) t.Fatal(err)
} }
rd := reader{ rd := reader{
values: data, values: data,
@ -161,25 +161,25 @@ func TestDefaultResolver(t *testing.T) {
case int: case int:
if actual, err = v.Int(); err == nil { if actual, err = v.Int(); err == nil {
if !reflect.DeepEqual(test.expect.(int), int(actual.(int64))) { if !reflect.DeepEqual(test.expect.(int), int(actual.(int64))) {
t.Fatal(`expect is not equal to actual`) t.Fatal("expect is not equal to actual")
} }
} }
case string: case string:
if actual, err = v.String(); err == nil { if actual, err = v.String(); err == nil {
if !reflect.DeepEqual(test.expect, actual) { if !reflect.DeepEqual(test.expect, actual) {
t.Fatal(`expect is not equal to actual`) t.Fatal("expect is not equal to actual")
} }
} }
case bool: case bool:
if actual, err = v.Bool(); err == nil { if actual, err = v.Bool(); err == nil {
if !reflect.DeepEqual(test.expect, actual) { if !reflect.DeepEqual(test.expect, actual) {
t.Fatal(`expect is not equal to actual`) t.Fatal("expect is not equal to actual")
} }
} }
case float64: case float64:
if actual, err = v.Float(); err == nil { if actual, err = v.Float(); err == nil {
if !reflect.DeepEqual(test.expect, actual) { if !reflect.DeepEqual(test.expect, actual) {
t.Fatal(`expect is not equal to actual`) t.Fatal("expect is not equal to actual")
} }
} }
default: default:

@ -8,11 +8,11 @@ import (
"strings" "strings"
"sync" "sync"
"github.com/go-kratos/kratos/v2/log"
"github.com/imdario/mergo" "github.com/imdario/mergo"
"google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
"github.com/go-kratos/kratos/v2/log"
) )
// Reader is config reader. // Reader is config reader.
@ -38,9 +38,7 @@ func newReader(opts options) Reader {
} }
func (r *reader) Merge(kvs ...*KeyValue) error { func (r *reader) Merge(kvs ...*KeyValue) error {
r.lock.Lock() merged, err := r.cloneMap()
merged, err := cloneMap(r.values)
r.lock.Unlock()
if err != nil { if err != nil {
return err return err
} }
@ -79,6 +77,12 @@ func (r *reader) Resolve() error {
return r.opts.resolver(r.values) return r.opts.resolver(r.values)
} }
func (r *reader) cloneMap() (map[string]interface{}, error) {
r.lock.Lock()
defer r.lock.Unlock()
return cloneMap(r.values)
}
func cloneMap(src map[string]interface{}) (map[string]interface{}, error) { func cloneMap(src map[string]interface{}) (map[string]interface{}, error) {
// https://gist.github.com/soroushjp/0ec92102641ddfc3ad5515ca76405f4d // https://gist.github.com/soroushjp/0ec92102641ddfc3ad5515ca76405f4d
var buf bytes.Buffer var buf bytes.Buffer
@ -90,12 +94,12 @@ func cloneMap(src map[string]interface{}) (map[string]interface{}, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
var copy map[string]interface{} var clone map[string]interface{}
err = dec.Decode(&copy) err = dec.Decode(&clone)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return copy, nil return clone, nil
} }
func convertMap(src interface{}) interface{} { func convertMap(src interface{}) interface{} {

@ -29,7 +29,7 @@ func TestReader_Merge(t *testing.T) {
Format: "json", Format: "json",
}) })
if err == nil { if err == nil {
t.Fatal(`err is nil`) t.Fatal("err is nil")
} }
err = r.Merge(&KeyValue{ err = r.Merge(&KeyValue{
@ -38,15 +38,15 @@ func TestReader_Merge(t *testing.T) {
Format: "json", Format: "json",
}) })
if err != nil { if err != nil {
t.Fatal(`err is not nil`) t.Fatal(err)
} }
vv, ok := r.Value("nice") vv, ok := r.Value("nice")
if !ok { if !ok {
t.Fatal(`ok is false`) t.Fatal("ok is false")
} }
vvv, err := vv.String() vvv, err := vv.String()
if err != nil { if err != nil {
t.Fatal(`err is not nil`) t.Fatal(err)
} }
if vvv != "boat" { if vvv != "boat" {
t.Fatal(`vvv is not equal to "boat"`) t.Fatal(`vvv is not equal to "boat"`)
@ -58,18 +58,18 @@ func TestReader_Merge(t *testing.T) {
Format: "json", Format: "json",
}) })
if err != nil { if err != nil {
t.Fatal(`err is not nil`) t.Fatal(err)
} }
vv, ok = r.Value("x") vv, ok = r.Value("x")
if !ok { if !ok {
t.Fatal(`ok is false`) t.Fatal("ok is false")
} }
vvx, err := vv.Int() vvx, err := vv.Int()
if err != nil { if err != nil {
t.Fatal(`err is not nil`) t.Fatal(err)
} }
if int64(2) != vvx { if vvx != 2 {
t.Fatal(`vvx is not equal to 2`) t.Fatal("vvx is not equal to 2")
} }
} }
@ -118,27 +118,27 @@ a:
r := newReader(opts) r := newReader(opts)
err := r.Merge(&test.kv) err := r.Merge(&test.kv)
if err != nil { if err != nil {
t.Fatal(`err is not nil`) t.Fatal(err)
} }
vv, ok := r.Value("a.b.X") vv, ok := r.Value("a.b.X")
if !ok { if !ok {
t.Fatal(`ok is false`) t.Fatal("ok is false")
} }
vvv, err := vv.Int() vvv, err := vv.Int()
if err != nil { if err != nil {
t.Fatal(`err is not nil`) t.Fatal(err)
} }
if int64(1) != vvv { if int64(1) != vvv {
t.Fatal(`vvv is not equal to 1`) t.Fatal("vvv is not equal to 1")
} }
vv, ok = r.Value("a.b.Y") vv, ok = r.Value("a.b.Y")
if !ok { if !ok {
t.Fatal(`ok is false`) t.Fatal("ok is false")
} }
vvy, err := vv.String() vvy, err := vv.String()
if err != nil { if err != nil {
t.Fatal(`err is not nil`) t.Fatal(err)
} }
if vvy != "lol" { if vvy != "lol" {
t.Fatal(`vvy is not equal to "lol"`) t.Fatal(`vvy is not equal to "lol"`)
@ -146,29 +146,29 @@ a:
vv, ok = r.Value("a.b.z") vv, ok = r.Value("a.b.z")
if !ok { if !ok {
t.Fatal(`ok is false`) t.Fatal("ok is false")
} }
vvz, err := vv.Bool() vvz, err := vv.Bool()
if err != nil { if err != nil {
t.Fatal(`err is not nil`) t.Fatal(err)
} }
if !vvz { if !vvz {
t.Fatal(`vvz is not equal to true`) t.Fatal("vvz is not equal to true")
} }
_, ok = r.Value("aasasdg=234l.asdfk,") _, ok = r.Value("aasasdg=234l.asdfk,")
if ok { if ok {
t.Fatal(`ok is true`) t.Fatal("ok is true")
} }
_, ok = r.Value("aas......asdg=234l.asdfk,") _, ok = r.Value("aas......asdg=234l.asdfk,")
if ok { if ok {
t.Fatal(`ok is true`) t.Fatal("ok is true")
} }
_, ok = r.Value("a.b.Y.") _, ok = r.Value("a.b.Y.")
if ok { if ok {
t.Fatal(`ok is true`) t.Fatal("ok is true")
} }
}) })
} }
@ -192,11 +192,11 @@ func TestReader_Source(t *testing.T) {
Format: "json", Format: "json",
}) })
if err != nil { if err != nil {
t.Fatal(`err is not nil`) t.Fatal(err)
} }
b, err := r.Source() b, err := r.Source()
if err != nil { if err != nil {
t.Fatal(`err is not nil`) t.Fatal(err)
} }
if !reflect.DeepEqual([]byte(`{"a":{"b":{"X":1}}}`), b) { if !reflect.DeepEqual([]byte(`{"a":{"b":{"X":1}}}`), b) {
t.Fatal("[]byte(`{\"a\":{\"b\":{\"X\":1}}}`) is not equal to b") t.Fatal("[]byte(`{\"a\":{\"b\":{\"X\":1}}}`) is not equal to b")

@ -1,7 +1,7 @@
package config package config
import ( import (
stdjson "encoding/json" "encoding/json"
"fmt" "fmt"
"reflect" "reflect"
"strconv" "strconv"
@ -10,7 +10,7 @@ import (
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
"github.com/go-kratos/kratos/v2/encoding/json" kratosjson "github.com/go-kratos/kratos/v2/encoding/json"
) )
var ( var (
@ -36,6 +36,10 @@ type atomicValue struct {
atomic.Value atomic.Value
} }
func (v *atomicValue) typeAssertError() error {
return fmt.Errorf("type assert to %v failed", reflect.TypeOf(v.Load()))
}
func (v *atomicValue) Bool() (bool, error) { func (v *atomicValue) Bool() (bool, error) {
switch val := v.Load().(type) { switch val := v.Load().(type) {
case bool: case bool:
@ -43,7 +47,7 @@ func (v *atomicValue) Bool() (bool, error) {
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, string: case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, string:
return strconv.ParseBool(fmt.Sprint(val)) return strconv.ParseBool(fmt.Sprint(val))
} }
return false, fmt.Errorf("type assert to %v failed", reflect.TypeOf(v.Load())) return false, v.typeAssertError()
} }
func (v *atomicValue) Int() (int64, error) { func (v *atomicValue) Int() (int64, error) {
@ -73,35 +77,37 @@ func (v *atomicValue) Int() (int64, error) {
case float64: case float64:
return int64(val), nil return int64(val), nil
case string: case string:
return strconv.ParseInt(val, 10, 64) //nolint:gomnd return strconv.ParseInt(val, 10, 64)
} }
return 0, fmt.Errorf("type assert to %v failed", reflect.TypeOf(v.Load())) return 0, v.typeAssertError()
} }
func (v *atomicValue) Slice() ([]Value, error) { func (v *atomicValue) Slice() ([]Value, error) {
if vals, ok := v.Load().([]interface{}); ok { vals, ok := v.Load().([]interface{})
var slices []Value if !ok {
for _, val := range vals { return nil, v.typeAssertError()
a := &atomicValue{}
a.Store(val)
slices = append(slices, a)
}
return slices, nil
} }
return nil, fmt.Errorf("type assert to %v failed", reflect.TypeOf(v.Load())) slices := make([]Value, 0, len(vals))
for _, val := range vals {
a := new(atomicValue)
a.Store(val)
slices = append(slices, a)
}
return slices, nil
} }
func (v *atomicValue) Map() (map[string]Value, error) { func (v *atomicValue) Map() (map[string]Value, error) {
if vals, ok := v.Load().(map[string]interface{}); ok { vals, ok := v.Load().(map[string]interface{})
m := make(map[string]Value, len(vals)) if !ok {
for key, val := range vals { return nil, v.typeAssertError()
a := new(atomicValue) }
a.Store(val) m := make(map[string]Value, len(vals))
m[key] = a for key, val := range vals {
} a := new(atomicValue)
return m, nil a.Store(val)
m[key] = a
} }
return nil, fmt.Errorf("type assert to %v failed", reflect.TypeOf(v.Load())) return m, nil
} }
func (v *atomicValue) Float() (float64, error) { func (v *atomicValue) Float() (float64, error) {
@ -131,9 +137,9 @@ func (v *atomicValue) Float() (float64, error) {
case float64: case float64:
return val, nil return val, nil
case string: case string:
return strconv.ParseFloat(val, 64) //nolint:gomnd return strconv.ParseFloat(val, 64)
} }
return 0.0, fmt.Errorf("type assert to %v failed", reflect.TypeOf(v.Load())) return 0.0, v.typeAssertError()
} }
func (v *atomicValue) String() (string, error) { func (v *atomicValue) String() (string, error) {
@ -147,7 +153,7 @@ func (v *atomicValue) String() (string, error) {
case fmt.Stringer: case fmt.Stringer:
return val.String(), nil return val.String(), nil
} }
return "", fmt.Errorf("type assert to %v failed", reflect.TypeOf(v.Load())) return "", v.typeAssertError()
} }
func (v *atomicValue) Duration() (time.Duration, error) { func (v *atomicValue) Duration() (time.Duration, error) {
@ -159,14 +165,14 @@ func (v *atomicValue) Duration() (time.Duration, error) {
} }
func (v *atomicValue) Scan(obj interface{}) error { func (v *atomicValue) Scan(obj interface{}) error {
data, err := stdjson.Marshal(v.Load()) data, err := json.Marshal(v.Load())
if err != nil { if err != nil {
return err return err
} }
if pb, ok := obj.(proto.Message); ok { if pb, ok := obj.(proto.Message); ok {
return json.UnmarshalOptions.Unmarshal(data, pb) return kratosjson.UnmarshalOptions.Unmarshal(data, pb)
} }
return stdjson.Unmarshal(data, obj) return json.Unmarshal(data, obj)
} }
type errValue struct { type errValue struct {

@ -6,17 +6,17 @@ import (
"time" "time"
) )
func Test_atomicValue_Bool(t *testing.T) { func TestAtomicValue_Bool(t *testing.T) {
vlist := []interface{}{"1", "t", "T", "true", "TRUE", "True", true, 1, int32(1)} vlist := []interface{}{"1", "t", "T", "true", "TRUE", "True", true, 1, int32(1)}
for _, x := range vlist { for _, x := range vlist {
v := atomicValue{} v := atomicValue{}
v.Store(x) v.Store(x)
b, err := v.Bool() b, err := v.Bool()
if err != nil { if err != nil {
t.Fatal(`err is not nil`) t.Fatal(err)
} }
if !b { if !b {
t.Fatal(`b is not equal to true`) t.Fatal("b is not equal to true")
} }
} }
@ -26,10 +26,10 @@ func Test_atomicValue_Bool(t *testing.T) {
v.Store(x) v.Store(x)
b, err := v.Bool() b, err := v.Bool()
if err != nil { if err != nil {
t.Fatal(`err is not nil`) t.Fatal(err)
} }
if b { if b {
t.Fatal(`b is not equal to false`) t.Fatal("b is not equal to false")
} }
} }
@ -39,22 +39,22 @@ func Test_atomicValue_Bool(t *testing.T) {
v.Store(x) v.Store(x)
_, err := v.Bool() _, err := v.Bool()
if err == nil { if err == nil {
t.Fatal(`err is nil`) t.Fatal("err is nil")
} }
} }
} }
func Test_atomicValue_Int(t *testing.T) { func TestAtomicValue_Int(t *testing.T) {
vlist := []interface{}{"123123", float64(123123), int64(123123), int32(123123), 123123} vlist := []interface{}{"123123", float64(123123), int64(123123), int32(123123), 123123}
for _, x := range vlist { for _, x := range vlist {
v := atomicValue{} v := atomicValue{}
v.Store(x) v.Store(x)
b, err := v.Int() b, err := v.Int()
if err != nil { if err != nil {
t.Fatal(`err is not nil`) t.Fatal(err)
} }
if b != 123123 { if b != 123123 {
t.Fatal(`b is not equal to 123123`) t.Fatal("b is not equal to 123123")
} }
} }
@ -64,22 +64,22 @@ func Test_atomicValue_Int(t *testing.T) {
v.Store(x) v.Store(x)
_, err := v.Int() _, err := v.Int()
if err == nil { if err == nil {
t.Fatal(`err is nil`) t.Fatal("err is nil")
} }
} }
} }
func Test_atomicValue_Float(t *testing.T) { func TestAtomicValue_Float(t *testing.T) {
vlist := []interface{}{"123123.1", 123123.1} vlist := []interface{}{"123123.1", 123123.1}
for _, x := range vlist { for _, x := range vlist {
v := atomicValue{} v := atomicValue{}
v.Store(x) v.Store(x)
b, err := v.Float() b, err := v.Float()
if err != nil { if err != nil {
t.Fatal(`err is not nil`) t.Fatal(err)
} }
if b != 123123.1 { if b != 123123.1 {
t.Fatal(`b is not equal to 123123.1`) t.Fatal("b is not equal to 123123.1")
} }
} }
@ -89,7 +89,7 @@ func Test_atomicValue_Float(t *testing.T) {
v.Store(x) v.Store(x)
_, err := v.Float() _, err := v.Float()
if err == nil { if err == nil {
t.Fatal(`err is nil`) t.Fatal("err is nil")
} }
} }
} }
@ -103,17 +103,17 @@ func (t ts) String() string {
return fmt.Sprintf("%s%d", t.Name, t.Age) return fmt.Sprintf("%s%d", t.Name, t.Age)
} }
func Test_atomicValue_String(t *testing.T) { func TestAtomicValue_String(t *testing.T) {
vlist := []interface{}{"1", float64(1), int64(1), 1, int64(1)} vlist := []interface{}{"1", float64(1), int64(1), 1, int64(1)}
for _, x := range vlist { for _, x := range vlist {
v := atomicValue{} v := atomicValue{}
v.Store(x) v.Store(x)
b, err := v.String() b, err := v.String()
if err != nil { if err != nil {
t.Fatal(`err is not nil`) t.Fatal(err)
} }
if b != "1" { if b != "1" {
t.Fatal(`b is not equal to 1`) t.Fatal("b is not equal to 1")
} }
} }
@ -121,7 +121,7 @@ func Test_atomicValue_String(t *testing.T) {
v.Store(true) v.Store(true)
b, err := v.String() b, err := v.String()
if err != nil { if err != nil {
t.Fatal(`err is not nil`) t.Fatal(err)
} }
if b != "true" { if b != "true" {
t.Fatal(`b is not equal to "true"`) t.Fatal(`b is not equal to "true"`)
@ -134,48 +134,48 @@ func Test_atomicValue_String(t *testing.T) {
}) })
b, err = v.String() b, err = v.String()
if err != nil { if err != nil {
t.Fatal(`err is not nil`) t.Fatal(err)
} }
if b != "test10" { if b != "test10" {
t.Fatal(`b is not equal to "test10"`) t.Fatal(`b is not equal to "test10"`)
} }
} }
func Test_atomicValue_Duration(t *testing.T) { func TestAtomicValue_Duration(t *testing.T) {
vlist := []interface{}{int64(5)} vlist := []interface{}{int64(5)}
for _, x := range vlist { for _, x := range vlist {
v := atomicValue{} v := atomicValue{}
v.Store(x) v.Store(x)
b, err := v.Duration() b, err := v.Duration()
if err != nil { if err != nil {
t.Fatal(`err is not nil`) t.Fatal(err)
} }
if b != time.Duration(5) { if b != time.Duration(5) {
t.Fatal(`b is not equal to time.Duration(5)`) t.Fatal("b is not equal to time.Duration(5)")
} }
} }
} }
func Test_atomicValue_Slice(t *testing.T) { func TestAtomicValue_Slice(t *testing.T) {
vlist := []interface{}{int64(5)} vlist := []interface{}{int64(5)}
v := atomicValue{} v := atomicValue{}
v.Store(vlist) v.Store(vlist)
slices, err := v.Slice() slices, err := v.Slice()
if err != nil { if err != nil {
t.Fatal(`err is not nil`) t.Fatal(err)
} }
for _, v := range slices { for _, v := range slices {
b, err := v.Duration() b, err := v.Duration()
if err != nil { if err != nil {
t.Fatal(`err is not nil`) t.Fatal(err)
} }
if b != time.Duration(5) { if b != time.Duration(5) {
t.Fatal(`b is not equal to time.Duration(5)`) t.Fatal("b is not equal to time.Duration(5)")
} }
} }
} }
func Test_atomicValue_Map(t *testing.T) { func TestAtomicValue_Map(t *testing.T) {
vlist := make(map[string]interface{}) vlist := make(map[string]interface{})
vlist["5"] = int64(5) vlist["5"] = int64(5)
vlist["text"] = "text" vlist["text"] = "text"
@ -183,21 +183,21 @@ func Test_atomicValue_Map(t *testing.T) {
v.Store(vlist) v.Store(vlist)
m, err := v.Map() m, err := v.Map()
if err != nil { if err != nil {
t.Fatal(`err is not nil`) t.Fatal(err)
} }
for k, v := range m { for k, v := range m {
if k == "5" { if k == "5" {
b, err := v.Duration() b, err := v.Duration()
if err != nil { if err != nil {
t.Fatal(`err is not nil`) t.Fatal(err)
} }
if b != time.Duration(5) { if b != time.Duration(5) {
t.Fatal(`b is not equal to time.Duration(5)`) t.Fatal("b is not equal to time.Duration(5)")
} }
} else { } else {
b, err := v.String() b, err := v.String()
if err != nil { if err != nil {
t.Fatal(`err is not nil`) t.Fatal(err)
} }
if b != "text" { if b != "text" {
t.Fatal(`b is not equal to "text"`) t.Fatal(`b is not equal to "text"`)
@ -206,20 +206,19 @@ func Test_atomicValue_Map(t *testing.T) {
} }
} }
func Test_atomicValue_Scan(t *testing.T) { func TestAtomicValue_Scan(t *testing.T) {
var err error
v := atomicValue{} v := atomicValue{}
err = v.Scan(&struct { err := v.Scan(&struct {
A string `json:"a"` A string `json:"a"`
}{"a"}) }{"a"})
if err != nil { if err != nil {
t.Fatal(`err is not nil`) t.Fatal(err)
} }
err = v.Scan(&struct { err = v.Scan(&struct {
A string `json:"a"` A string `json:"a"`
}{"a"}) }{"a"})
if err != nil { if err != nil {
t.Fatal(`err is not nil`) t.Fatal(err)
} }
} }

@ -4,8 +4,11 @@ go 1.16
require ( require (
github.com/DataDog/datadog-go v4.8.3+incompatible github.com/DataDog/datadog-go v4.8.3+incompatible
github.com/Microsoft/go-winio v0.5.2 // indirect
github.com/go-kratos/kratos/v2 v2.5.2 github.com/go-kratos/kratos/v2 v2.5.2
) )
require (
github.com/Microsoft/go-winio v0.5.2 // indirect
)
replace github.com/go-kratos/kratos/v2 => ../../../ replace github.com/go-kratos/kratos/v2 => ../../../

Loading…
Cancel
Save