From 4ee9c7834b94766fe1c44685a209b1ef5e3f0703 Mon Sep 17 00:00:00 2001 From: shockerli Date: Tue, 16 Nov 2021 11:05:05 +0800 Subject: [PATCH] improve indirect --- README.md | 7 +++---- README_ZH.md | 9 ++++----- bool.go | 4 ++-- cvte.go | 15 +++++++-------- float.go | 2 +- int.go | 4 ++-- slice.go | 23 ++++++++++++++--------- string.go | 2 +- time.go | 2 +- 9 files changed, 35 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 52e7135..3e97371 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ go get -u github.com/shockerli/cvt ## Usage -[中文说明](README_ZH.md) +English | [中文](README_ZH.md) ### with `error` @@ -113,9 +113,8 @@ cvt.Float("hello", 12.34) // 12.34 ### slice - `ColumnsE`: the values from a single column in the input array/slice/map of struct/map, `[]interface{}` - `FieldE`: the field value from map/struct, `interface{}` -- `KeysE`: the keys of map, `[]interface{}` -- `Slice` -- `SliceE`: convert an interface to a `[]interface{}` type +- `KeysE`: the keys of map, or fields of struct, `[]interface{}` +- `Slice` / `SliceE`: convert an interface to a `[]interface{}` type - `SliceIntE`: convert an interface to a `[]int` type - `SliceInt64E`: convert an interface to a `[]int64` type - `SliceFloat64E`: convert an interface to a `[]float64` type diff --git a/README_ZH.md b/README_ZH.md index a8d1c43..46533cf 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -7,7 +7,7 @@ [![codecov](https://codecov.io/gh/shockerli/cvt/branch/master/graph/badge.svg)](https://codecov.io/gh/shockerli/cvt) ![GitHub](https://img.shields.io/github/license/shockerli/cvt) -> 简单、安全的转换任意类型值,包括自定义类型 +> 一个简单、安全、高效的转换任意数据类型的 Go 语言工具包,支持自定义类型、提取结构体字段和值 ## 安装 @@ -17,7 +17,7 @@ go get -u github.com/shockerli/cvt ## 使用 -[English](README.md) +中文 | [English](README.md) ### 支持 `error` @@ -111,9 +111,8 @@ cvt.Float("hello", 12.34) // 12.34 ### slice - `ColumnsE`: 类似于 PHP 中的 `array_column`,`FieldE` 函数的切片版本,返回 `[]interface{}` - `FieldE`: 取 `map` 或 `struct` 的字段值,返回 `interface{}` -- `KeysE`: 取 `map` 的键名,返回 `[]interface{}` -- `Slice` -- `SliceE`: 转换成 `[]interface{}` +- `KeysE`: 取 `map` 的键名,或结构体的字段名,返回 `[]interface{}` +- `Slice` / `SliceE`: 转换成 `[]interface{}` - `SliceIntE`: 转换成 `[]int` - `SliceInt64E`: 转换成 `[]int64` - `SliceFloat64E`: 转换成 `[]float64` diff --git a/bool.go b/bool.go index 2d54558..30b7eba 100644 --- a/bool.go +++ b/bool.go @@ -21,7 +21,7 @@ func Bool(v interface{}, def ...bool) bool { // BoolE convert an interface to a bool type func BoolE(val interface{}) (bool, error) { - v, rk, rv := indirect(val) + v, rv := indirect(val) switch vv := v.(type) { case bool: @@ -40,7 +40,7 @@ func BoolE(val interface{}) (bool, error) { return false, nil } - switch rk.Kind() { + switch rv.Kind() { // by elem length case reflect.Array, reflect.Slice, reflect.Map: return rv.Len() > 0, nil diff --git a/cvte.go b/cvte.go index 2665a45..6a9f7f0 100644 --- a/cvte.go +++ b/cvte.go @@ -22,9 +22,9 @@ func FieldE(val interface{}, field interface{}) (interface{}, error) { } sf := String(field) // match with the String of field, so field can be any type - _, rt, rv := indirect(val) + _, rv := indirect(val) - switch rt.Kind() { + switch rv.Kind() { case reflect.Map: // key of map for _, key := range rv.MapKeys() { if String(key.Interface()) == sf { @@ -42,10 +42,10 @@ func FieldE(val interface{}, field interface{}) (interface{}, error) { } // return the values of struct fields, and deep find the embedded fields -func deepStructValues(rt reflect.Type, rv reflect.Value) (sl []interface{}) { +func deepStructValues(rv reflect.Value) (sl []interface{}) { for j := 0; j < rv.NumField(); j++ { - if rt.Field(j).Anonymous { - sl = append(sl, deepStructValues(rt.Field(j).Type, rv.Field(j))...) + if rv.Type().Field(j).Anonymous { + sl = append(sl, deepStructValues(rv.Field(j))...) } else if rv.Field(j).CanInterface() { sl = append(sl, rv.Field(j).Interface()) } @@ -63,16 +63,15 @@ func sortedMapKeys(v reflect.Value) (s []reflect.Value) { } // returns the value with base type -func indirect(a interface{}) (val interface{}, rt reflect.Type, rv reflect.Value) { +func indirect(a interface{}) (val interface{}, rv reflect.Value) { if a == nil { return } - rt = reflect.TypeOf(a) rv = reflect.ValueOf(a) val = rv.Interface() - switch rt.Kind() { + switch rv.Kind() { case reflect.Ptr: // indirect the base type, if is been referenced many times for rv.Kind() == reflect.Ptr { // stop indirect until nil, avoid stack overflow diff --git a/float.go b/float.go index 6b9503b..c0b7e28 100644 --- a/float.go +++ b/float.go @@ -21,7 +21,7 @@ func Float64(v interface{}, def ...float64) float64 { // Float64E convert an interface to a float64 type func Float64E(val interface{}) (float64, error) { - v, _, rv := indirect(val) + v, rv := indirect(val) switch vv := v.(type) { case nil: diff --git a/int.go b/int.go index 38b441e..1cafb0c 100644 --- a/int.go +++ b/int.go @@ -330,7 +330,7 @@ func convUint64(val interface{}) (uint64, error) { } // indirect type - v, _, rv := indirect(val) + v, rv := indirect(val) switch vv := v.(type) { case nil: return 0, nil @@ -423,7 +423,7 @@ func convInt64(val interface{}) (int64, error) { } // indirect type - v, _, rv := indirect(val) + v, rv := indirect(val) switch vv := v.(type) { case nil: return 0, nil diff --git a/slice.go b/slice.go index aa01b94..dc48359 100644 --- a/slice.go +++ b/slice.go @@ -24,9 +24,9 @@ func SliceE(val interface{}) (sl []interface{}, err error) { return nil, errUnsupportedTypeNil } - _, rt, rv := indirect(val) + _, rv := indirect(val) - switch rt.Kind() { + switch rv.Kind() { case reflect.String: for _, vvv := range rv.String() { sl = append(sl, vvv) @@ -43,7 +43,7 @@ func SliceE(val interface{}) (sl []interface{}, err error) { } return case reflect.Struct: - sl = deepStructValues(rt, rv) + sl = deepStructValues(rv) return } @@ -128,9 +128,9 @@ func ColumnsE(val interface{}, field interface{}) (sl []interface{}, err error) return nil, errUnsupportedTypeNil } - _, rt, rv := indirect(val) + _, rv := indirect(val) - switch rt.Kind() { + switch rv.Kind() { case reflect.Slice, reflect.Array: for j := 0; j < rv.Len(); j++ { vv, e := FieldE(rv.Index(j).Interface(), field) @@ -152,7 +152,7 @@ func ColumnsE(val interface{}, field interface{}) (sl []interface{}, err error) return } - return nil, fmt.Errorf("unsupported type: %s", rt.Name()) + return nil, fmt.Errorf("unsupported type: %s", rv.Type().Name()) } // KeysE return the keys of map, sorted by asc @@ -161,15 +161,20 @@ func KeysE(val interface{}) (sl []interface{}, err error) { return nil, errUnsupportedTypeNil } - _, rt, rv := indirect(val) + _, rv := indirect(val) - switch rt.Kind() { + switch rv.Kind() { case reflect.Map: for _, key := range sortedMapKeys(rv) { sl = append(sl, key.Interface()) } return + // case reflect.Struct: + // for _, v := range deepStructFields(rv.Type()) { + // sl = append(sl, v) + // } + // return } - return nil, fmt.Errorf("unsupported type: %s", rt.Name()) + return nil, fmt.Errorf("unsupported type: %s", rv.Type().Name()) } diff --git a/string.go b/string.go index fdc9a3b..ba6b5e4 100644 --- a/string.go +++ b/string.go @@ -57,7 +57,7 @@ func StringE(val interface{}) (string, error) { } // indirect type - v, _, rv := indirect(val) + v, rv := indirect(val) switch vv := v.(type) { case nil: return "", nil diff --git a/time.go b/time.go index 72b8feb..d7d174c 100644 --- a/time.go +++ b/time.go @@ -20,7 +20,7 @@ func Time(v interface{}, def ...time.Time) time.Time { // TimeE convert an interface to a time.Time type func TimeE(val interface{}) (t time.Time, err error) { - v, _, _ := indirect(val) + v, _ := indirect(val) // source type switch vv := v.(type) {