diff --git a/define.go b/define.go index 1df5f37..f8c377e 100644 --- a/define.go +++ b/define.go @@ -7,7 +7,10 @@ // Date : 2023-05-05 14:44 package wrapper -import "time" +import ( + "git.zhangdeman.cn/zhangdeman/easymap" + "time" +) // Int8Result ... // @@ -465,7 +468,7 @@ type StringSliceResult struct { // // Date : 16:05 2023/8/10 type MapResult struct { - Value Map + Value easymap.EasyMap Err error } diff --git a/easymap.go b/easymap.go new file mode 100644 index 0000000..cbd2a56 --- /dev/null +++ b/easymap.go @@ -0,0 +1,88 @@ +// Package wrapper ... +// +// Description : wrapper ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 2023-08-10 15:01 +package wrapper + +import ( + "encoding/json" + "errors" + "git.zhangdeman.cn/zhangdeman/easymap" + "git.zhangdeman.cn/zhangdeman/serialize" + "github.com/tidwall/gjson" + "reflect" +) + +// EasyMap ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 15:02 2023/8/10 +func EasyMap(mapData any) easymap.EasyMap { + m, _ := EasyMapWithError(mapData) + return m +} + +// EasyMapWithError 转换map,并带上转换的异常 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 15:06 2023/8/10 +func EasyMapWithError(mapData any) (easymap.EasyMap, error) { + if nil == mapData { + return easymap.NewNormal(), nil + } + m := easymap.NewNormal() + reflectType := reflect.TypeOf(mapData) + if reflectType.Kind() != reflect.Map { + mapFormatData := make(map[string]any) + if err := serialize.JSON.UnmarshalWithNumber(serialize.JSON.MarshalForByteIgnoreError(mapData), &mapFormatData); nil != err { + return m, errors.New("input data type is " + reflectType.String() + ", can not convert to map") + } + mapData = mapFormatData + } + + reflectValue := reflect.ValueOf(mapData).MapRange() + for reflectValue.Next() { + // 循环提取相关值 + m.Set(reflectValue.Key().Interface(), reflectValue.Value().Interface()) + } + return m, nil +} + +// EasyMapFromStruct 从struct转map +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 16:11 2023/8/10 +func EasyMapFromStruct(data any) easymap.EasyMap { + byteData, _ := json.Marshal(data) + return EasyMapFromByte(byteData) +} + +// EasyMapFromString 从string转为Map +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 16:12 2023/8/10 +func EasyMapFromString(data string) easymap.EasyMap { + return EasyMapFromByte([]byte(data)) +} + +// EasyMapFromByte 从字节数组转为Map +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 16:12 2023/8/10 +func EasyMapFromByte(data []byte) easymap.EasyMap { + res := easymap.NewNormal() + jsonRes := gjson.Parse(string(data)) + jsonRes.ForEach(func(key, value gjson.Result) bool { + res.Set(key.Value(), value.Value()) + return true + }) + return res +} diff --git a/map.go b/map.go index 6013835..16ae07c 100644 --- a/map.go +++ b/map.go @@ -4,92 +4,226 @@ // // Author : go_developer@163.com<白茶清欢> // -// Date : 2023-08-10 15:01 +// Date : 2024-11-06 18:27 package wrapper import ( - "encoding/json" "errors" - "git.zhangdeman.cn/zhangdeman/easymap" "git.zhangdeman.cn/zhangdeman/serialize" - "github.com/tidwall/gjson" "reflect" + "sync" ) -// EasyMap ... -// -// Author : go_developer@163.com<白茶清欢> -// -// Date : 15:02 2023/8/10 -func EasyMap(mapData any) Map { - m, _ := EasyMapWithError(mapData) - return m +var mapLock = &sync.RWMutex{} + +type Map map[string]any + +func (m *Map) lock() { + mapLock.Lock() } -// EasyMapWithError 转换map,并带上转换的异常 +func (m *Map) unlock() { + mapLock.Unlock() +} + +func (m *Map) rLock() { + mapLock.RLock() +} + +func (m *Map) rUnlock() { + mapLock.RUnlock() +} + +// Exist key是否存在 // // Author : go_developer@163.com<白茶清欢> // -// Date : 15:06 2023/8/10 -func EasyMapWithError(mapData any) (Map, error) { - if nil == mapData { - return easymap.NewNormal(), nil +// Date : 18:34 2024/11/6 +func (m *Map) Exist(key string) bool { + if m.IsNil() { + return false } - m := easymap.NewNormal() - reflectType := reflect.TypeOf(mapData) - if reflectType.Kind() != reflect.Map { - mapFormatData := make(map[string]any) - if err := serialize.JSON.UnmarshalWithNumber(serialize.JSON.MarshalForByteIgnoreError(mapData), &mapFormatData); nil != err { - return m, errors.New("input data type is " + reflectType.String() + ", can not convert to map") - } - mapData = mapFormatData + m.rLock() + defer m.rUnlock() + v := *m + _, exist := v[key] + return exist +} + +// Set 设置map的值, 字段如果已存在, 会覆盖 +// +// 参数说明: +// - field : 摇摆存的字段 +// - value : 字段对应的值 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 15:16 2024/11/19 +func (m *Map) Set(field string, value any) error { + if m.IsNil() { + return errors.New("Map is nil") } + m.lock() + defer m.unlock() + (*m)[field] = value + return nil +} - reflectValue := reflect.ValueOf(mapData).MapRange() - for reflectValue.Next() { - // 循环提取相关值 - m.Set(reflectValue.Key().Interface(), reflectValue.Value().Interface()) +// Del 删除指定的字段 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 15:21 2024/11/19 +func (m *Map) Del(field string) { + if m.IsNil() { + return } - return m, nil + m.lock() + defer m.unlock() + delete(*m, field) } -// EasyMapFromStruct 从struct转map +// IsNil 判断map是否为nil // // Author : go_developer@163.com<白茶清欢> // -// Date : 16:11 2023/8/10 -func EasyMapFromStruct(data any) Map { - byteData, _ := json.Marshal(data) - return EasyMapFromByte(byteData) -} - -// EasyMapFromString 从string转为Map -// -// Author : go_developer@163.com<白茶清欢> -// -// Date : 16:12 2023/8/10 -func EasyMapFromString(data string) Map { - return EasyMapFromByte([]byte(data)) -} - -// EasyMapFromByte 从字节数组转为Map -// -// Author : go_developer@163.com<白茶清欢> -// -// Date : 16:12 2023/8/10 -func EasyMapFromByte(data []byte) Map { - res := easymap.NewNormal() - jsonRes := gjson.Parse(string(data)) - jsonRes.ForEach(func(key, value gjson.Result) bool { - res.Set(key.Value(), value.Value()) +// Date : 15:22 2024/11/19 +func (m *Map) IsNil() bool { + if nil == m { return true - }) + } + return reflect.ValueOf(*m).IsNil() +} + +// Get ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 14:41 2024/11/19 +func (m *Map) Get(field string) (any, error) { + if m.IsNil() { + return nil, errors.New("map is nil") + } + m.rLock() + defer m.rUnlock() + v := *m + val, exist := v[field] + if !exist { + return nil, errors.New(field + " : field not found") + } + return val, nil +} + +// GetDefault 获取指定字段, 不存在则设置默认值 +// +// 参数说明: +// - field : 要读取的字段 +// - defaultValue : 字段不存在返回的默认值 +// - allowNil : 字段存在, 但是值为Nil, 是否是一个合法值 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 14:59 2024/11/19 +func (m *Map) GetDefault(field string, defaultValue any, allowNil bool) any { + if m.IsNil() { + return defaultValue + } + m.rLock() + defer m.rUnlock() + v := *m + val, exist := v[field] + if !exist { + return defaultValue + } + if nil == val { + if allowNil { + return val + } + return defaultValue + } + return val +} + +// Value 获取数据值 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 19:39 2024/11/6 +func (m *Map) Value() map[string]any { + if m.IsNil() { + return nil + } + return *m +} + +// Clone 克隆数据 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 19:40 2024/11/6 +func (m *Map) Clone() Map { + newData := map[string]any{} + if m.IsNil() { + return newData + } + m.rLock() + defer m.rUnlock() + mapValue := m.Value() + for k, v := range mapValue { + newData[k] = v + } + return newData +} + +// Filter 过滤指定字段 +// +// 参数说明: +// - fieldList : 要保留的字段列表 +// - ignoreNotFound : 指定字段不存在是否忽略,如不忽略, 字段不存在, 将会报错 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 14:40 2024/11/19 +func (m *Map) Filter(fieldList []string, ignoreNotFound bool) (map[string]any, error) { + res := make(map[string]any) + for _, itemField := range fieldList { + if val, err := m.Get(itemField); err == nil { + res[itemField] = val + } else { + if !ignoreNotFound { + return nil, err + } + } + } + return res, nil +} + +// FilterDefault 过滤指定字段, 字段不存储在则用默认值填充 +// +// 参数说明: +// - fieldMap : 查询字段表, key为要查询的字段, value为 字段不存在时返回的默认值 +// - allowNil : 字段存在, 三只值为你来是否是一个合法值 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 15:07 2024/11/19 +func (m *Map) FilterDefault(fieldMap map[string]any, allowNil bool) map[string]any { + res := make(map[string]any) + for itemField, fieldDefaultValue := range fieldMap { + res[itemField] = m.GetDefault(itemField, fieldDefaultValue, allowNil) + } return res } -// Map ... +// MarshalJSON Map序列化 // // Author : go_developer@163.com<白茶清欢> // -// Date : 15:14 2023/8/10 -type Map easymap.EasyMap +// Date : 15:35 2024/11/19 +func (m *Map) MarshalJSON() ([]byte, error) { + mapData := m.Value() + if nil == mapData { + return nil, nil + } + return serialize.JSON.MarshalForByte(mapData) +} diff --git a/map_test.go b/map_test.go new file mode 100644 index 0000000..58652ee --- /dev/null +++ b/map_test.go @@ -0,0 +1,47 @@ +// Package wrapper ... +// +// Description : wrapper ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 2024-11-06 18:37 +package wrapper + +import ( + "fmt" + "testing" +) + +func TestMap_Exist(t *testing.T) { + testData := Map(map[string]any{ + "name": "zhang", + }) + fmt.Println(testData.Exist("name")) + fmt.Println(testData.Exist("age")) +} + +func TestMap_IsNil(t *testing.T) { + var ( + m Map + m1 *Map + ) + fmt.Println(m.Set("a", 1)) + fmt.Println(m.IsNil(), m1.IsNil()) +} + +func TestMap_IsMasher(t *testing.T) { + var ( + m Map + m1 = Map(map[string]any{ + "a": 1, + "b": m, + "c": Map(map[string]any{ + "name": "de", + }), + }) + ) + d, err := m.MarshalJSON() + fmt.Println(string(d), err) + d, err = m1.MarshalJSON() + fmt.Println(string(d), err) +}