49 Commits

Author SHA1 Message Date
50aa5ae7f8 数组支持提取指定路径字段, 转换成list 2024-08-06 16:03:12 +08:00
3533617196 update go mod 2024-08-06 15:23:20 +08:00
9ff1c213bb 计算字符串hash nimber 2024-06-27 11:17:06 +08:00
8d056baada Merge branch 'master' of git.zhangdeman.cn:zhangdeman/wrapper 2024-06-12 16:38:58 +08:00
ed0c57913a 完善any2string 2024-06-12 16:38:51 +08:00
588df729e0 变更 interface{} => any 2024-06-08 20:06:35 +08:00
3faebb9145 Merge branch 'master' of git.zhangdeman.cn:zhangdeman/wrapper 2024-05-20 20:47:54 +08:00
5163fd6f49 修复EasyMapFromByte的BUG 2024-05-20 20:47:44 +08:00
e228983e73 优化uniqueue返回值 2024-05-06 15:00:32 +08:00
3caad964bc 升级数组操作 2024-05-06 14:56:35 +08:00
9ae0c8f4be 增加数组去重 2024-05-06 14:29:33 +08:00
d1b9779946 update go mod 2024-05-06 14:19:37 +08:00
8c922be06d array 增加 to string slice 2024-04-22 11:44:17 +08:00
ee726ea6bc 增加判断字符串是否包含子串方法 2024-04-19 18:39:25 +08:00
e125c7e75d update go mod 2024-03-20 12:07:04 +08:00
1e1db09499 增加包装的IsSame方法 2024-03-11 11:18:25 +08:00
65107176f4 Merge pull request '增加比较两个map某一个字段值是否相等的能力' (#4) from feature/diff into master
Reviewed-on: #4
2024-03-08 16:00:00 +08:00
c07adaf249 增加仅比较一个字段方法 2024-03-08 15:58:58 +08:00
4d25a2a650 对外暴露compare方法 2024-03-08 15:56:53 +08:00
ab1f877b3c 优化字符串数字的处理 2024-03-08 15:51:38 +08:00
e8fc0addfc 增加判断字段是否相等的默认实现 2024-03-08 15:46:14 +08:00
9b469e0ac2 增加diff基础信息的结构定义 2024-03-08 11:33:54 +08:00
270c4fcfd4 update go mod 2024-03-08 11:00:51 +08:00
75fd00c4cf update go mod 2024-01-23 10:42:58 +08:00
5a53679400 优化toAnySlice 2024-01-23 10:42:03 +08:00
448b472c53 版本比较,增加ignore error 2023-12-27 18:20:49 +08:00
6da972b112 migrate ConverAssign 2023-12-27 17:59:33 +08:00
d7e591277a Merge branch 'master' of git.zhangdeman.cn:zhangdeman/wrapper 2023-12-27 17:52:55 +08:00
88d3066307 增加版本号比较工具 2023-12-27 17:52:48 +08:00
d9aed3d800 适配EasyMap 2023-12-24 22:53:27 +08:00
a427bc63c5 优化any -> string 2023-12-06 21:32:22 +08:00
1dd7ccf026 包装try/catch 2023-11-29 11:59:54 +08:00
e7417048fb 增加三元运算法支持 2023-11-28 16:27:31 +08:00
1b71c40d14 update go mod 2023-11-23 17:08:00 +08:00
31780bd924 优化slince转字符串 2023-10-25 17:46:15 +08:00
91eca55f87 增加struct => wrapper.Map的能力 2023-10-12 18:50:56 +08:00
0a9175daa8 规划any各种类型的转换 2023-10-11 17:22:29 +08:00
3432f85c3d 增加转为对象的能力 2023-10-11 17:20:03 +08:00
160f464d15 优化数据类型获取 2023-10-11 15:16:00 +08:00
8b1a515cb9 数据类型获取的存储 2023-10-11 15:05:01 +08:00
c641e6003b update go mod 2023-10-11 14:34:49 +08:00
9f0b7008a4 增加转为字符串 2023-09-28 17:01:42 +08:00
faafa8ee2a 包装类型支持转为时间类型 2023-09-04 20:35:42 +08:00
2886126ae7 修复map类型可能panic问题 2023-08-27 14:40:13 +08:00
8308761f72 array in -> has 2023-08-26 14:02:51 +08:00
14bc4c2c9d 修复Md5的bug 2023-08-11 22:23:16 +08:00
cfc46e8d82 update func 2023-08-11 15:15:13 +08:00
bff3fa8566 切换序列化库 2023-08-11 13:56:40 +08:00
65186fe23b 优化代码 2023-08-11 13:49:14 +08:00
24 changed files with 1839 additions and 382 deletions

74
any.go
View File

@ -7,17 +7,24 @@
// Date : 2023-06-01 18:18
package wrapper
import "reflect"
import (
"fmt"
"git.zhangdeman.cn/zhangdeman/consts"
"git.zhangdeman.cn/zhangdeman/serialize"
"reflect"
)
// AnyDataType ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 18:19 2023/6/1
func AnyDataType(data interface{}) *AnyType {
return &AnyType{
func AnyDataType(data any) *AnyType {
at := &AnyType{
data: data,
}
at.dataType = at.Type()
return at
}
// AnyType ...
@ -26,7 +33,8 @@ func AnyDataType(data interface{}) *AnyType {
//
// Date : 18:19 2023/6/1
type AnyType struct {
data interface{}
data any
dataType string
}
// IsNil 是否为 nil
@ -44,23 +52,33 @@ func (at *AnyType) IsNil() bool {
//
// Date : 18:22 2023/6/1
func (at *AnyType) Type() string {
if len(at.dataType) > 0 {
// 已经处理过的,无需在处理
return at.dataType
}
if at.IsNil() {
return DataTypeNil
return consts.DataTypeNil
}
reflectType := reflect.TypeOf(at.data)
switch reflectType.Kind() {
case reflect.Slice:
return DataTypeAnySlice
case reflect.Array:
return DataTypeAnySlice
case reflect.Map:
return DataTypeAnyObject
case reflect.Struct:
return DataTypeAnyObject
case reflect.String:
return consts.DataTypeString
case reflect.Slice, reflect.Array:
return consts.DataTypeSliceAny
case reflect.Map, reflect.Struct:
return consts.DataTypeMapAnyAny
case reflect.Pointer:
return DataTypePtr
return consts.DataTypePtr
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return consts.DataTypeInt
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return consts.DataTypeUint
case reflect.Bool:
return consts.DataTypeBool
case reflect.Float32, reflect.Float64:
return consts.DataTypeFloat
default:
return reflectType.Kind().String()
return consts.DataTypeUnknown
}
}
@ -69,6 +87,28 @@ func (at *AnyType) Type() string {
// Author : go_developer@163.com<白茶清欢>
//
// Date : 18:32 2023/6/1
func (at *AnyType) ToString() string {
return ""
func (at *AnyType) ToString() String {
dataType := at.Type()
switch dataType {
case consts.DataTypeUnknown, consts.DataTypeNil:
return String("")
case consts.DataTypeString:
return String(fmt.Sprintf("%v", at.data))
case consts.DataTypeSliceAny:
var val []any
_ = serialize.JSON.Transition(at.data, &val)
return String(ArrayType[any, any](val).ToString().Value)
case consts.DataTypeMapAnyAny:
return String(EasyMap(at.data).ToString())
case consts.DataTypeInt:
return String(Int(at.data.(int64)).ToString().Value)
case consts.DataTypeUint:
return String(Int(at.data.(uint)).ToString().Value)
case consts.DataTypeFloat:
return String(Float(at.data.(float64)).ToString().Value)
case consts.DataTypeBool:
return String(fmt.Sprintf("%v", at.data))
default:
return String(serialize.JSON.MarshalForString(at.data))
}
}

323
array.go
View File

@ -10,35 +10,33 @@ package wrapper
import (
"encoding/json"
"errors"
"fmt"
"git.zhangdeman.cn/zhangdeman/op_type"
"github.com/tidwall/gjson"
"reflect"
"strings"
)
// Array 数组实例
// ArrayType 数组实例
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 21:03 2023/6/11
func Array(value interface{}) *ArrayType {
at := &ArrayType{
func ArrayType[Bt op_type.BaseType, ExtractDataType op_type.BaseType](value []Bt) *Array[Bt, ExtractDataType] {
at := &Array[Bt, ExtractDataType]{
value: value,
}
at.Convert()
return at
}
// ArrayType ...
// Array ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 21:05 2023/6/11
type ArrayType struct {
value interface{}
convertResult []interface{}
convertErr error
isSimpleSlice bool // 是否简单list, 即数据的每一项类型相同, 且都是基础内置数据类型
itemType reflect.Kind // 简单list场景下, 每一项的数据类型
type Array[Bt op_type.BaseType, ExtractDataType op_type.BaseType] struct {
value []Bt
convertErr error
itemType reflect.Kind // 简单list场景下, 每一项的数据类型
}
// IsNil 输入是否为nil
@ -46,175 +44,22 @@ type ArrayType struct {
// Author : go_developer@163.com<白茶清欢>
//
// Date : 21:11 2023/6/11
func (at *ArrayType) IsNil() bool {
func (at *Array[Bt, ExtractDataType]) IsNil() bool {
return at.value == nil
}
// IsValid 检测是否为数组类型
// ToStringSlice ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 21:06 2023/6/11
func (at *ArrayType) IsValid() bool {
if at.IsNil() {
return false
// Date : 11:42 2024/4/22
func (at *Array[Bt, ExtractDataType]) ToStringSlice() []string {
list := make([]string, 0)
for _, item := range at.value {
byteData, _ := json.Marshal(item)
list = append(list, strings.Trim(string(byteData), "\""))
}
byteData, err := json.Marshal(at.value)
if nil != err {
return false
}
return strings.HasPrefix(string(byteData), "[") && strings.HasSuffix(string(byteData), "]")
}
// ItemIsInterface 数组每一项是否为interface
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 21:20 2023/6/11
func (at *ArrayType) ItemIsInterface() bool {
if !at.IsValid() {
return false
}
if _, ok := at.value.([]interface{}); ok {
return true
}
return false
}
// Convert 类型转换
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:59 2023/6/12
func (at *ArrayType) Convert() ([]interface{}, error) {
if at.IsNil() {
// 空指针
at.convertResult = make([]interface{}, 0)
return at.convertResult, nil
}
if !at.IsValid() {
// 无效slice
at.convertErr = errors.New("input slice is invalid")
return nil, at.convertErr
}
switch val := at.value.(type) {
case []int8:
at.isSimpleSlice = true
at.itemType = reflect.Int8
at.convertResult = make([]interface{}, len(val))
for i := 0; i < len(val); i++ {
at.convertResult[i] = val[i]
}
case []int16:
at.isSimpleSlice = true
at.itemType = reflect.Int16
at.convertResult = make([]interface{}, len(val))
for i := 0; i < len(val); i++ {
at.convertResult[i] = val[i]
}
case []int32:
at.isSimpleSlice = true
at.itemType = reflect.Int32
at.convertResult = make([]interface{}, len(val))
for i := 0; i < len(val); i++ {
at.convertResult[i] = val[i]
}
case []int64:
at.isSimpleSlice = true
at.itemType = reflect.Int64
at.convertResult = make([]interface{}, len(val))
for i := 0; i < len(val); i++ {
at.convertResult[i] = val[i]
}
case []int:
at.isSimpleSlice = true
at.itemType = reflect.Int
at.convertResult = make([]interface{}, len(val))
for i := 0; i < len(val); i++ {
at.convertResult[i] = val[i]
}
case []uint:
at.isSimpleSlice = true
at.itemType = reflect.Uint
at.convertResult = make([]interface{}, len(val))
for i := 0; i < len(val); i++ {
at.convertResult[i] = val[i]
}
case []uint8:
at.isSimpleSlice = true
at.itemType = reflect.Uint8
at.convertResult = make([]interface{}, len(val))
for i := 0; i < len(val); i++ {
at.convertResult[i] = val[i]
}
case []uint16:
at.isSimpleSlice = true
at.itemType = reflect.Uint16
at.convertResult = make([]interface{}, len(val))
for i := 0; i < len(val); i++ {
at.convertResult[i] = val[i]
}
case []uint32:
at.isSimpleSlice = true
at.itemType = reflect.Int32
at.convertResult = make([]interface{}, len(val))
for i := 0; i < len(val); i++ {
at.convertResult[i] = val[i]
}
case []uint64:
at.isSimpleSlice = true
at.itemType = reflect.Int64
at.convertResult = make([]interface{}, len(val))
for i := 0; i < len(val); i++ {
at.convertResult[i] = val[i]
}
case []float32:
at.isSimpleSlice = true
at.itemType = reflect.Float32
at.convertResult = make([]interface{}, len(val))
for i := 0; i < len(val); i++ {
at.convertResult[i] = val[i]
}
case []float64:
at.isSimpleSlice = true
at.itemType = reflect.Float64
at.convertResult = make([]interface{}, len(val))
for i := 0; i < len(val); i++ {
at.convertResult[i] = val[i]
}
case []bool:
at.isSimpleSlice = true
at.itemType = reflect.Bool
at.convertResult = make([]interface{}, len(val))
for i := 0; i < len(val); i++ {
at.convertResult[i] = val[i]
}
case []string:
at.isSimpleSlice = true
at.itemType = reflect.String
at.convertResult = make([]interface{}, len(val))
for i := 0; i < len(val); i++ {
at.convertResult[i] = val[i]
}
case []interface{}:
at.isSimpleSlice = false
at.itemType = reflect.Interface
at.convertResult = make([]interface{}, len(val))
for i := 0; i < len(val); i++ {
at.convertResult[i] = val[i]
}
}
return at.convertResult, nil
}
// ConvertIgnoreError 类型转换并忽略异常
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 18:07 2023/6/26
func (at *ArrayType) ConvertIgnoreError() []interface{} {
res, _ := at.Convert()
return res
return list
}
// Unique 对数据结果进行去重
@ -222,45 +67,38 @@ func (at *ArrayType) ConvertIgnoreError() []interface{} {
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:43 2023/6/12
func (at *ArrayType) Unique() []interface{} {
result := make([]interface{}, 0)
if at.isSimpleSlice {
// 简单数据类型
dataTable := make(map[string]bool)
for _, item := range at.convertResult {
k := fmt.Sprintf("%v", item)
if _, exist := dataTable[k]; exist {
continue
}
dataTable[k] = true
result = append(result, item)
func (at *Array[Bt, ExtractDataType]) Unique() []Bt {
result := make([]Bt, 0)
dataTable := make(map[string]bool)
for _, item := range at.value {
byteData, _ := json.Marshal(item)
k := string(byteData)
if strings.HasPrefix(k, "\"\"") && strings.HasSuffix(k, "\"\"") {
k = string(byteData[1 : len(byteData)-1])
}
return result
if _, exist := dataTable[k]; exist {
continue
}
dataTable[k] = true
result = append(result, item)
}
return []interface{}{}
return result
}
// In 查询一个值是否在列表里, 在的话, 返回首次出现的索引, 不在返回-1
// Has 查询一个值是否在列表里, 在的话, 返回首次出现的索引, 不在返回-1
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:28 2023/7/31
func (at *ArrayType) In(input interface{}) int {
for idx := 0; idx < len(at.convertResult); idx++ {
if nil == input {
if nil != at.convertResult[idx] {
continue
}
return idx
}
if at.convertResult[idx] == nil {
continue
}
if reflect.TypeOf(at.convertResult[idx]).String() != reflect.TypeOf(input).String() {
func (at *Array[Bt, ExtractDataType]) Has(input Bt) int {
for idx := 0; idx < len(at.value); idx++ {
if reflect.TypeOf(at.value[idx]).String() != reflect.TypeOf(input).String() {
// 类型不同
continue
}
sourceByte, _ := json.Marshal(at.convertResult[idx])
sourceByte, _ := json.Marshal(at.value[idx])
inputByte, _ := json.Marshal(input)
if string(sourceByte) != string(inputByte) {
continue
@ -269,3 +107,84 @@ func (at *ArrayType) In(input interface{}) int {
}
return -1
}
// ToString ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:57 2023/9/28
func (at *Array[Bt, ExtractDataType]) ToString() StringResult {
if at.IsNil() {
return StringResult{
Value: "",
Err: nil,
}
}
byteData, err := json.Marshal(at.value)
return StringResult{
Value: string(byteData),
Err: err,
}
}
// ToStringWithSplit 数组按照指定分隔符转为字符串
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:42 2023/10/25
func (at *Array[Bt, ExtractDataType]) ToStringWithSplit(split string) StringResult {
if at.IsNil() {
return StringResult{
Value: "",
Err: nil,
}
}
return StringResult{
Value: strings.Join(at.ToStringSlice(), split),
Err: nil,
}
}
// ExtractField 提取指定字段, 转换成数组
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:24 2024/8/6
func (at *Array[Bt, ExtractDataType]) ExtractField(fieldPath string) ([]ExtractDataType, error) {
strValResult := at.ToString()
if nil != strValResult.Err {
return make([]ExtractDataType, 0), nil
}
gjsonResult := gjson.Parse(strValResult.Value)
if !gjsonResult.IsArray() {
return make([]ExtractDataType, 0), errors.New("input value is not slice")
}
arrList := gjsonResult.Array()
if len(arrList) == 0 {
return make([]ExtractDataType, 0), nil
}
res := make([]ExtractDataType, 0)
for _, item := range arrList {
valueResult := item.Get(fieldPath)
if !valueResult.Exists() {
// 不存在
continue
}
var val ExtractDataType
if err := ConvertAssign(&val, valueResult.String()); nil != err {
return nil, err
}
res = append(res, val)
}
return res, nil
}
// ExtractFieldIgnoreError 提取指定字段并忽略异常
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:28 2024/8/6
func (at *Array[Bt, ExtractDataType]) ExtractFieldIgnoreError(field string) []ExtractDataType {
res, _ := at.ExtractField(field)
return res
}

View File

@ -4,29 +4,33 @@
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2023-06-11 21:12
// Date : 2024-05-06 下午2:48
package wrapper
import (
"fmt"
"reflect"
"testing"
)
func TestArray(t *testing.T) {
val := []interface{}{1, 2, 3}
fmt.Println(Array(val).IsValid())
fmt.Println(Array(val).ItemIsInterface())
valInt := []int{1, 2, 3, 1, 4, 5, 6, 7, 7, 6, 9}
fmt.Println(Array(valInt).Unique())
a := map[string]interface{}{"name": "zhang"}
b := a
c := map[string]interface{}{"name": "de"}
fmt.Println(reflect.DeepEqual(b, c))
fmt.Println(reflect.DeepEqual(a, b))
fmt.Println(Array(valInt).In("1"))
fmt.Println(Array(valInt).In(1))
fmt.Println(Array(valInt).In(2))
fmt.Println(Array(valInt).In(7))
fmt.Println(Array(valInt).In(20))
func TestArray_Unique(t *testing.T) {
fmt.Println(ArrayType[any, any]([]any{"1", 1, 1, "1", 2, 3}).Unique())
fmt.Println(ArrayType[int, any]([]int{1, 1, 2, 3}).Unique())
}
func TestArray_ExtractField(t *testing.T) {
testMap := []any{
map[string]any{
"age": 18,
"name": "baicha",
},
map[string]any{
"age": 20,
"name": "qinghuan",
},
map[string]any{
"foo": "bar",
},
}
fmt.Println(ArrayType[any, int](testMap).ExtractField("age"))
fmt.Println(ArrayType[any, string](testMap).ExtractField("name"))
}

394
convert.go Normal file
View File

@ -0,0 +1,394 @@
// Package wrapper ...
//
// Description : 任意类型之间的相互转换
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2021-02-23 10:23 下午
package wrapper
/*
Desc : 在处理一些参数的时候,可能需要将参数转换为各种类型,这里实现一个通用的转换函数,实现各种类型之间的相互转换。
当然如果源数据格式和目标数据类型不一致是会返回错误的。例如将字符串“一二三”转换为数值类型则会报错而将字符串“123”转换为数值类型则OK。
这段代码实际抄自go自带的“database/sql”库只是源代码作为内部函数无法在外面调用可以单独把需要的功能拎出来使用
代码中有一个Scaner接口可以自行实现然后通过"convertAssign()"函数作为dst参数传入。
Author : zhangdeman001@ke.com<白茶清欢>
*/
import (
"errors"
"fmt"
"reflect"
"strconv"
"time"
)
// RawBytes is a byte slice that holds a reference to memory owned by
// the database itself. After a Scan into a RawBytes, the slice is only
// valid until the next call to Next, Scan, or Close.
type RawBytes []byte
var errNilPtr = errors.New("destination pointer is nil") // embedded in descriptive error
// ConvertAssign ...
// convertAssign copies to dest the value in src, converting it if possible.
// An error is returned if the copy would result in loss of information.
// dest should be a pointer type.
func ConvertAssign(dest, src any) error {
// Common cases, without reflect.
switch s := src.(type) {
case string:
switch d := dest.(type) {
case *string:
if d == nil {
return errNilPtr
}
*d = s
return nil
case *[]byte:
if d == nil {
return errNilPtr
}
*d = []byte(s)
return nil
case *RawBytes:
if d == nil {
return errNilPtr
}
*d = append((*d)[:0], s...)
return nil
}
case []byte:
switch d := dest.(type) {
case *string:
if d == nil {
return errNilPtr
}
*d = string(s)
return nil
case *any:
if d == nil {
return errNilPtr
}
*d = cloneBytes(s)
return nil
case *[]byte:
if d == nil {
return errNilPtr
}
*d = cloneBytes(s)
return nil
case *RawBytes:
if d == nil {
return errNilPtr
}
*d = s
return nil
}
case time.Time:
switch d := dest.(type) {
case *time.Time:
*d = s
return nil
case *string:
*d = s.Format(time.RFC3339Nano)
return nil
case *[]byte:
if d == nil {
return errNilPtr
}
*d = []byte(s.Format(time.RFC3339Nano))
return nil
case *RawBytes:
if d == nil {
return errNilPtr
}
*d = s.AppendFormat((*d)[:0], time.RFC3339Nano)
return nil
}
case nil:
switch d := dest.(type) {
case *any:
if d == nil {
return errNilPtr
}
*d = nil
return nil
case *[]byte:
if d == nil {
return errNilPtr
}
*d = nil
return nil
case *RawBytes:
if d == nil {
return errNilPtr
}
*d = nil
return nil
}
}
var sv reflect.Value
switch d := dest.(type) {
case *string:
sv = reflect.ValueOf(src)
switch sv.Kind() {
case reflect.Bool,
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
reflect.Float32, reflect.Float64:
*d = asString(src)
return nil
}
case *[]byte:
sv = reflect.ValueOf(src)
if b, ok := asBytes(nil, sv); ok {
*d = b
return nil
}
case *RawBytes:
sv = reflect.ValueOf(src)
if b, ok := asBytes([]byte(*d)[:0], sv); ok {
*d = RawBytes(b)
return nil
}
case *bool:
bv, err := Bool.ConvertValue(src)
if err == nil {
*d = bv.(bool)
}
return err
case *any:
*d = src
return nil
}
if scanner, ok := dest.(Scanner); ok {
return scanner.Scan(src)
}
dpv := reflect.ValueOf(dest)
if dpv.Kind() != reflect.Ptr {
return errors.New("destination not a pointer")
}
if dpv.IsNil() {
return errNilPtr
}
if !sv.IsValid() {
sv = reflect.ValueOf(src)
}
dv := reflect.Indirect(dpv)
if sv.IsValid() && sv.Type().AssignableTo(dv.Type()) {
switch b := src.(type) {
case []byte:
dv.Set(reflect.ValueOf(cloneBytes(b)))
default:
dv.Set(sv)
}
return nil
}
if dv.Kind() == sv.Kind() && sv.Type().ConvertibleTo(dv.Type()) {
dv.Set(sv.Convert(dv.Type()))
return nil
}
// The following conversions use a string value as an intermediate representation
// to convert between various numeric types.
//
// This also allows scanning into user defined types such as "type Int int64".
// For symmetry, also check for string destination types.
switch dv.Kind() {
case reflect.Ptr:
if src == nil {
dv.Set(reflect.Zero(dv.Type()))
return nil
}
dv.Set(reflect.New(dv.Type().Elem()))
return ConvertAssign(dv.Interface(), src)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
s := asString(src)
i64, err := strconv.ParseInt(s, 10, dv.Type().Bits())
if err != nil {
err = strconvErr(err)
return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err)
}
dv.SetInt(i64)
return nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
s := asString(src)
u64, err := strconv.ParseUint(s, 10, dv.Type().Bits())
if err != nil {
err = strconvErr(err)
return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err)
}
dv.SetUint(u64)
return nil
case reflect.Float32, reflect.Float64:
s := asString(src)
f64, err := strconv.ParseFloat(s, dv.Type().Bits())
if err != nil {
err = strconvErr(err)
return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err)
}
dv.SetFloat(f64)
return nil
case reflect.String:
switch v := src.(type) {
case string:
dv.SetString(v)
return nil
case []byte:
dv.SetString(string(v))
return nil
}
}
return fmt.Errorf("unsupported Scan, storing driver.Value type %T into type %T", src, dest)
}
func strconvErr(err error) error {
if ne, ok := err.(*strconv.NumError); ok {
return ne.Err
}
return err
}
func cloneBytes(b []byte) []byte {
if b == nil {
return nil
}
c := make([]byte, len(b))
copy(c, b)
return c
}
func ToString(src any) string {
return asString(src)
}
func asString(src any) string {
switch v := src.(type) {
case string:
return v
case []byte:
return string(v)
}
rv := reflect.ValueOf(src)
switch rv.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return strconv.FormatInt(rv.Int(), 10)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return strconv.FormatUint(rv.Uint(), 10)
case reflect.Float64:
return strconv.FormatFloat(rv.Float(), 'g', -1, 64)
case reflect.Float32:
return strconv.FormatFloat(rv.Float(), 'g', -1, 32)
case reflect.Bool:
return strconv.FormatBool(rv.Bool())
}
return fmt.Sprintf("%v", src)
}
func asBytes(buf []byte, rv reflect.Value) (b []byte, ok bool) {
switch rv.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return strconv.AppendInt(buf, rv.Int(), 10), true
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return strconv.AppendUint(buf, rv.Uint(), 10), true
case reflect.Float32:
return strconv.AppendFloat(buf, rv.Float(), 'g', -1, 32), true
case reflect.Float64:
return strconv.AppendFloat(buf, rv.Float(), 'g', -1, 64), true
case reflect.Bool:
return strconv.AppendBool(buf, rv.Bool()), true
case reflect.String:
s := rv.String()
return append(buf, s...), true
}
return
}
// Value is a value that drivers must be able to handle.
// It is either nil, a type handled by a database driver's NamedValueChecker
// interface, or an instance of one of these types:
//
// int64
// float64
// bool
// []byte
// string
// time.Time
type Value any
type boolType struct{}
var Bool boolType
func (boolType) String() string { return "Bool" }
func (boolType) ConvertValue(src any) (Value, error) {
switch s := src.(type) {
case bool:
return s, nil
case string:
b, err := strconv.ParseBool(s)
if err != nil {
return nil, fmt.Errorf("sql/driver: couldn't convert %q into type bool", s)
}
return b, nil
case []byte:
b, err := strconv.ParseBool(string(s))
if err != nil {
return nil, fmt.Errorf("sql/driver: couldn't convert %q into type bool", s)
}
return b, nil
}
sv := reflect.ValueOf(src)
switch sv.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
iv := sv.Int()
if iv == 1 || iv == 0 {
return iv == 1, nil
}
return nil, fmt.Errorf("sql/driver: couldn't convert %d into type bool", iv)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
uv := sv.Uint()
if uv == 1 || uv == 0 {
return uv == 1, nil
}
return nil, fmt.Errorf("sql/driver: couldn't convert %d into type bool", uv)
}
return nil, fmt.Errorf("sql/driver: couldn't convert %v (%T) into type bool", src, src)
}
type Scanner interface {
// Scan assigns a value from a database driver.
//
// The src value will be of one of the following types:
//
// int64
// float64
// bool
// []byte
// string
// time.Time
// nil - for NULL values
//
// An error should be returned if the value cannot be stored
// without loss of information.
//
// Reference types such as []byte are only valid until the next call to Scan
// and should not be retained. Their underlying memory is owned by the driver.
// If retention is necessary, copy their values before the next call to Scan.
Scan(src any) error
}

View File

@ -7,45 +7,7 @@
// Date : 2023-05-05 14:44
package wrapper
const (
DataTypeUnknown = "unknown"
DataTypeNil = "nil"
DataTypeAny = "interface"
DataTypePtr = "ptr"
DataTypeString = "string"
DataTypeInt8 = "int8"
DataTypeInt16 = "int16"
DataTypeInt32 = "int32"
DataTypeInt64 = "int64"
DataTypeInt = "int"
DataTypeUint8 = "uint8"
DataTypeUint16 = "uint16"
DataTypeUint32 = "uint32"
DataTypeUint64 = "uint64"
DataTypeUint = "uint"
DataTypeBool = "bool"
DataTypeNumber = "number"
DataTypeFloat32 = "float32"
DataTypeFloat64 = "float64"
DataTypeDouble = "double"
DataTypeFloat = "float"
DataTypeIntSlice = "[]int"
DataTypeUntSlice = "[]uint"
DataTypeNumberSlice = "[]number"
DataTypeFloatSlice = "[]float"
DataTypeBoolSlice = "[]bool"
DataTypeAnySlice = "[]interface"
DataTypeObject = "map[string]interface"
DataTypeAnyObject = "map[interface]interface"
)
import "time"
// Int8Result ...
//
@ -293,7 +255,7 @@ type Float64PtrResult struct {
//
// Date : 16:40 2023/5/8
type Any struct {
Value interface{}
Value any
Err error
}
@ -323,7 +285,7 @@ type BoolPtrResult struct {
//
// Date : 16:38 2023/5/8
type ObjectResult struct {
Value map[string]interface{}
Value map[string]any
Err error
}
@ -477,6 +439,16 @@ type Float64SliceResult struct {
Err error
}
// DurationResult 时间转换结果
//
// Author : zhangdeman001@ke.com<张德满>
//
// Date : 20:32 2023/9/4
type DurationResult struct {
Value time.Duration
Err error
}
// StringSliceResult ...
//
// Author : go_developer@163.com<白茶清欢>
@ -487,16 +459,6 @@ type StringSliceResult struct {
Err error
}
// AnySliceResult ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 18:28 2023/5/8
type AnySliceResult struct {
Value []interface{}
Err error
}
// MapResult 转map的结果
//
// Author : go_developer@163.com<白茶清欢>
@ -506,3 +468,13 @@ type MapResult struct {
Value Map
Err error
}
// AnySliceResult ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 18:28 2023/5/8
type AnySliceResult struct {
Value []any
Err error
}

28
go.mod
View File

@ -1,22 +1,28 @@
module git.zhangdeman.cn/zhangdeman/wrapper
go 1.20
go 1.21
require git.zhangdeman.cn/zhangdeman/util v0.0.0-20230810063945-842592611562
toolchain go1.21.4
require (
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20230307094841-e437ba87af10 // indirect
github.com/BurntSushi/toml v1.3.2 // indirect
github.com/Jeffail/gabs v1.4.0 // indirect
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 // indirect
github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 // indirect
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240726024939-e424db29c5c4
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20240311030808-e2a2e6a3c211
git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20240618035451-8d48a6bd39dd
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394
github.com/spaolacci/murmur3 v1.1.0
github.com/stretchr/testify v1.8.4
github.com/tidwall/gjson v1.17.3
)
require (
git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e // indirect
github.com/BurntSushi/toml v1.4.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-ini/ini v1.67.0 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mozillazg/go-pinyin v0.20.0 // indirect
github.com/mssola/user_agent v0.6.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/tidwall/gjson v1.16.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect

56
go.sum
View File

@ -1,42 +1,58 @@
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20230307094841-e437ba87af10 h1:+Lg4vXFEiWVKjhUJdXuoP0AgjGT49oqJ3301STnZErk=
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20230307094841-e437ba87af10/go.mod h1:+Lc0zYF8sylRi75A7NGmObrLxugwAZa8WVpWh2eh5X0=
git.zhangdeman.cn/zhangdeman/util v0.0.0-20230801092344-773ac512f305 h1:6Bs/cQP+eKABHB/01uHQI15PwKbo7n8HNx7nIFUGBp0=
git.zhangdeman.cn/zhangdeman/util v0.0.0-20230801092344-773ac512f305/go.mod h1:trYFOShINaQBvinQrH4A0G2kfL22Y2lygEcAiGDt/sc=
git.zhangdeman.cn/zhangdeman/util v0.0.0-20230810063945-842592611562 h1:wo0r4mexqkPzQ1SZOw5z8A7FJ3ne1G6A/qWR3iaqlhw=
git.zhangdeman.cn/zhangdeman/util v0.0.0-20230810063945-842592611562/go.mod h1:trYFOShINaQBvinQrH4A0G2kfL22Y2lygEcAiGDt/sc=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240104123641-b3f23974e5d6 h1:ytpXTP3oxp480BAZQoOzqlBP4XP73NcpMplZ1/fA1lQ=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240104123641-b3f23974e5d6/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240419080457-9d9562469008 h1:6z99+X/B/G9sCZ+aTLYGWk3YLVVODzevA4wjWj9jvq0=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240419080457-9d9562469008/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240501142503-e31a270e50cc h1:kPz9xiUVruM8kwbUUVpxyCTX8pGgyKt60K5zX77oyC4=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240501142503-e31a270e50cc/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240608124542-4d97bd80dc68 h1:AaWKU0bKHnNot24OMhaOCBKtpfhz4o05DKHrRFgYd8M=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240608124542-4d97bd80dc68/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240612081722-31c64d4d4ce7 h1:QR8vMXOTy0NFKdodsGKA4gTNHJMfob3yRFYMXrZj7ek=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240612081722-31c64d4d4ce7/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240726024939-e424db29c5c4 h1:mibnyzYbZullK0aTHVASHl3UeoVr8IgytQZsuyv+yEM=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240726024939-e424db29c5c4/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20240130062251-a87a97b0e8d4 h1:93JYY8JLbFcrlq37q/uKyxs2r2e3modsjvfSbnZQ/UI=
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20240130062251-a87a97b0e8d4/go.mod h1:SrtvrQRdzt+8KfYzvosH++gWxo2ShPTzR1m3VQ6uX7U=
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20240311030808-e2a2e6a3c211 h1:I/wOsRpCSRkU9vo1u703slQsmK0wnNeZzsWQOGtIAG0=
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20240311030808-e2a2e6a3c211/go.mod h1:SrtvrQRdzt+8KfYzvosH++gWxo2ShPTzR1m3VQ6uX7U=
git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0 h1:gUDlQMuJ4xNfP2Abl1Msmpa3fASLWYkNlqDFF/6GN0Y=
git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0/go.mod h1:VHb9qmhaPDAQDcS6vUiDCamYjZ4R5lD1XtVsh55KsMI=
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20240110090803-399e964daa0c h1:k7VCn9GfRGTilvdF/TcTFVMDBfKLe3VeGAtMTiDSnS0=
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20240110090803-399e964daa0c/go.mod h1:w7kG4zyTJ1uPFaTWhze+OQuaUBINT2XnDxpyiM6ctc0=
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20240325080031-1f58204e8687 h1:uQcGqdzi4UdpZlp4f4FUPeBqoygP58pEKJkmN3ROsE0=
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20240325080031-1f58204e8687/go.mod h1:gf7SW2TXATgux8pfdFedMkXWv2515OtIIM/5c4atkFw=
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20240618035451-8d48a6bd39dd h1:2Y37waOVCmVvx0Rp8VGEptE2/2JVMImtxB4dKKDk/3w=
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20240618035451-8d48a6bd39dd/go.mod h1:6+7whkCmb4sJDIfH3HxNuXRveaM0gCCNWd2uXZqNtIE=
git.zhangdeman.cn/zhangdeman/util v0.0.0-20231227095334-7eb5cdbf9253 h1:GO3oZa5a2sqwAzGcLDJtQzmshSWRmoP7IDS8bwFqvC4=
git.zhangdeman.cn/zhangdeman/util v0.0.0-20231227095334-7eb5cdbf9253/go.mod h1:VpPjBlwz8U+OxZuxzHQBv1aEEZ3pStH6bZvT21ADEbI=
git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e h1:Q973S6CcWr1ICZhFI1STFOJ+KUImCl2BaIXm6YppBqI=
git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e/go.mod h1:VpPjBlwz8U+OxZuxzHQBv1aEEZ3pStH6bZvT21ADEbI=
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/Jeffail/gabs v1.4.0 h1://5fYRRTq1edjfIrQGvdkcd22pkYUrHZ5YC/H2GJVAo=
github.com/Jeffail/gabs v1.4.0/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc=
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 h1:OYA+5W64v3OgClL+IrOD63t4i/RW7RqrAVl9LTZ9UqQ=
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394/go.mod h1:Q8n74mJTIgjX4RBBcHnJ05h//6/k6foqmgE45jTQtxg=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 h1:CaO/zOnF8VvUfEbhRatPcwKVWamvbYd8tQGRWacE9kU=
github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1/go.mod h1:+hnT3ywWDTAFrW5aE+u2Sa/wT555ZqwoCS+pk3p6ry4=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mozillazg/go-pinyin v0.20.0 h1:BtR3DsxpApHfKReaPO1fCqF4pThRwH9uwvXzm+GnMFQ=
github.com/mozillazg/go-pinyin v0.20.0/go.mod h1:iR4EnMMRXkfpFVV5FMi4FNB6wGq9NV6uDWbUuPhP4Yc=
github.com/mssola/user_agent v0.6.0 h1:uwPR4rtWlCHRFyyP9u2KOV0u8iQXmS7Z7feTrstQwk4=
github.com/mssola/user_agent v0.6.0/go.mod h1:TTPno8LPY3wAIEKRpAtkdMT0f8SE24pLRGPahjCH4uw=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/tidwall/gjson v1.16.0 h1:SyXa+dsSPpUlcwEDuKuEBJEz5vzTvOea+9rjyYodQFg=
github.com/tidwall/gjson v1.16.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/tidwall/gjson v1.17.3 h1:bwWLZU7icoKRG+C+0PNwIKC6FCJO/Q3p2pZvuP0jN94=
github.com/tidwall/gjson v1.17.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
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=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

13
int.go
View File

@ -10,6 +10,7 @@ package wrapper
import (
"fmt"
"math"
"time"
)
// Int int类型
@ -19,6 +20,18 @@ import (
// Date : 13:57 2023/5/5
type Int int64
// ToDuration ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 20:33 2023/9/4
func (i Int) ToDuration(timeUnit time.Duration) DurationResult {
return DurationResult{
Value: time.Duration(i.ToInt64().Value) * timeUnit,
Err: nil,
}
}
// ToInt8 ...
//
// Author : go_developer@163.com<白茶清欢>

32
map.go
View File

@ -8,10 +8,11 @@
package wrapper
import (
"bytes"
"encoding/json"
"errors"
"git.zhangdeman.cn/zhangdeman/easymap"
"git.zhangdeman.cn/zhangdeman/serialize"
"github.com/tidwall/gjson"
"reflect"
)
@ -20,7 +21,7 @@ import (
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:02 2023/8/10
func EasyMap(mapData interface{}) Map {
func EasyMap(mapData any) Map {
m, _ := EasyMapWithError(mapData)
return m
}
@ -30,11 +31,18 @@ func EasyMap(mapData interface{}) Map {
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:06 2023/8/10
func EasyMapWithError(mapData interface{}) (Map, error) {
m := easymap.NewNormal(true)
func EasyMapWithError(mapData any) (Map, error) {
if nil == mapData {
return easymap.NewNormal(), nil
}
m := easymap.NewNormal()
reflectType := reflect.TypeOf(mapData)
if reflectType.Kind() != reflect.Map {
return m, errors.New("input data type is " + reflectType.String() + ", not map")
mapFormatData := make(map[string]any)
if err := serialize.JSON.UnmarshalWithNumber(serialize.JSON.MarshalForByte(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()
@ -50,7 +58,7 @@ func EasyMapWithError(mapData interface{}) (Map, error) {
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:11 2023/8/10
func EasyMapFromStruct(data interface{}) Map {
func EasyMapFromStruct(data any) Map {
byteData, _ := json.Marshal(data)
return EasyMapFromByte(byteData)
}
@ -70,11 +78,13 @@ func EasyMapFromString(data string) Map {
//
// Date : 16:12 2023/8/10
func EasyMapFromByte(data []byte) Map {
var tmpMap map[interface{}]interface{}
decoder := json.NewDecoder(bytes.NewReader(data))
decoder.UseNumber()
_ = decoder.Decode(&tmpMap)
return EasyMap(tmpMap)
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
}
// Map ...

View File

@ -10,7 +10,7 @@ package wrapper
import (
"encoding/json"
"errors"
"git.zhangdeman.cn/zhangdeman/util"
"git.zhangdeman.cn/zhangdeman/serialize"
"reflect"
)
@ -19,10 +19,10 @@ import (
// Author : go_developer@163.com<白茶清欢>
//
// Date : 18:36 2023/6/1
func ObjectData(data interface{}) *ObjectType {
func ObjectData(data any) *ObjectType {
ot := &ObjectType{
source: data,
data: map[interface{}]interface{}{},
data: map[any]any{},
byteData: []byte{},
isValid: true,
invalidErr: errors.New("data is invalid"),
@ -37,7 +37,7 @@ func ObjectData(data interface{}) *ObjectType {
case reflect.Struct:
ot.byteData, _ = json.Marshal(ot.source)
default:
// 数据类型不是 nil / map / struct 质疑
// 数据类型不是 nil / map / struct 之一
ot.isValid = false
}
return ot
@ -49,8 +49,8 @@ func ObjectData(data interface{}) *ObjectType {
//
// Date : 18:38 2023/6/1
type ObjectType struct {
source interface{}
data map[interface{}]interface{}
source any
data map[any]any
byteData []byte
isValid bool
invalidErr error
@ -106,13 +106,13 @@ func (ot *ObjectType) ToString() StringResult {
// Date : 16:17 2023/6/2
func (ot *ObjectType) ToMapStringAny() ObjectResult {
res := ObjectResult{
Value: map[string]interface{}{},
Value: map[string]any{},
Err: nil,
}
if ot.IsNil() {
return res
}
res.Err = util.JSON.UnmarshalWithNumber(ot.byteData, &res.Value)
res.Err = serialize.JSON.UnmarshalWithNumber(ot.byteData, &res.Value)
return res
}
@ -121,14 +121,14 @@ func (ot *ObjectType) ToMapStringAny() ObjectResult {
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:41 2023/6/2
func (ot *ObjectType) ToStruct(receiver interface{}) error {
func (ot *ObjectType) ToStruct(receiver any) error {
if nil == receiver {
return errors.New("receiver is nil")
}
if ot.IsNil() {
return errors.New("data is nil")
}
return util.JSON.UnmarshalWithNumber(ot.byteData, receiver)
return serialize.JSON.UnmarshalWithNumber(ot.byteData, receiver)
}
// ToStructIgnoreErr ...
@ -136,12 +136,12 @@ func (ot *ObjectType) ToStruct(receiver interface{}) error {
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:42 2023/6/2
func (ot *ObjectType) ToStructIgnoreErr(receiver interface{}) {
func (ot *ObjectType) ToStructIgnoreErr(receiver any) {
if nil == receiver {
return
}
if ot.IsNil() {
return
}
_ = util.JSON.UnmarshalWithNumber(ot.byteData, receiver)
_ = serialize.JSON.UnmarshalWithNumber(ot.byteData, receiver)
}

274
string.go
View File

@ -9,12 +9,39 @@ package wrapper
import (
"crypto/md5"
"encoding/hex"
"errors"
"git.zhangdeman.cn/zhangdeman/util"
"git.zhangdeman.cn/zhangdeman/serialize"
"github.com/axgle/mahonia"
"github.com/spaolacci/murmur3"
"io"
"math/rand"
"strings"
"time"
)
// StringFromRandom 从随机字符串生成String
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:50 2023/8/11
func StringFromRandom(length int, sourceCharList string) String {
if length == 0 {
return ""
}
if len(sourceCharList) == 0 {
//字符串为空,默认字符源为如下(去除易混淆的i/l):
sourceCharList = "0123456789abcdefghjkmnopqrstuvwxyzABCDEFGHJKMNOPQRSTUVWXYZ"
}
strByte := []byte(sourceCharList)
var genStrByte = make([]byte, 0)
r := rand.New(rand.NewSource(time.Now().UnixNano()))
for i := 0; i < int(length); i++ {
genStrByte = append(genStrByte, strByte[r.Intn(len(strByte))])
}
return String(string(genStrByte))
}
// String 字符串类型包装
//
// Author : go_developer@163.com<白茶清欢>
@ -31,7 +58,7 @@ func (str String) ToFloat32() Float32Result {
var (
res Float32Result
)
res.Err = util.ConvertAssign(&res.Value, str)
res.Err = ConvertAssign(&res.Value, str)
return res
}
@ -63,7 +90,7 @@ func (str String) ToFloat64() Float64Result {
var (
res Float64Result
)
res.Err = util.ConvertAssign(&res.Value, str)
res.Err = ConvertAssign(&res.Value, str)
return res
}
@ -131,7 +158,7 @@ func (str String) ToInt8() Int8Result {
var (
res Int8Result
)
res.Err = util.ConvertAssign(&res.Value, str)
res.Err = ConvertAssign(&res.Value, str)
return res
}
@ -163,7 +190,7 @@ func (str String) ToInt16() Int16Result {
var (
res Int16Result
)
res.Err = util.ConvertAssign(&res.Value, str)
res.Err = ConvertAssign(&res.Value, str)
return res
}
@ -195,7 +222,7 @@ func (str String) ToInt32() Int32Result {
var (
res Int32Result
)
res.Err = util.ConvertAssign(&res.Value, str)
res.Err = ConvertAssign(&res.Value, str)
return res
}
@ -227,7 +254,7 @@ func (str String) ToInt64() Int64Result {
var (
res Int64Result
)
res.Err = util.ConvertAssign(&res.Value, str)
res.Err = ConvertAssign(&res.Value, str)
return res
}
@ -259,7 +286,7 @@ func (str String) ToInt() IntResult {
var (
res IntResult
)
res.Err = util.ConvertAssign(&res.Value, str)
res.Err = ConvertAssign(&res.Value, str)
return res
}
@ -291,7 +318,7 @@ func (str String) ToUint8() Uint8Result {
var (
res Uint8Result
)
res.Err = util.ConvertAssign(&res.Value, str)
res.Err = ConvertAssign(&res.Value, str)
return res
}
@ -323,7 +350,7 @@ func (str String) ToUint16() Uint16Result {
var (
res Uint16Result
)
res.Err = util.ConvertAssign(&res.Value, str)
res.Err = ConvertAssign(&res.Value, str)
return res
}
@ -355,7 +382,7 @@ func (str String) ToUint32() Uint32Result {
var (
res Uint32Result
)
res.Err = util.ConvertAssign(&res.Value, str)
res.Err = ConvertAssign(&res.Value, str)
return res
}
@ -387,7 +414,7 @@ func (str String) ToUint64() Uint64Result {
var (
res Uint64Result
)
res.Err = util.ConvertAssign(&res.Value, str)
res.Err = ConvertAssign(&res.Value, str)
return res
}
@ -419,7 +446,7 @@ func (str String) ToUint() UintResult {
var (
res UintResult
)
res.Err = util.ConvertAssign(&res.Value, str)
res.Err = ConvertAssign(&res.Value, str)
return res
}
@ -451,7 +478,7 @@ func (str String) ToBool() BoolResult {
var (
res BoolResult
)
res.Err = util.ConvertAssign(&res.Value, str)
res.Err = ConvertAssign(&res.Value, str)
return res
}
@ -495,11 +522,11 @@ func (str String) ToStringPtr() StringPtrResult {
func (str String) ToObject() ObjectResult {
var (
res = ObjectResult{
Value: map[string]interface{}{},
Value: map[string]any{},
Err: nil,
}
)
res.Err = util.JSON.UnmarshalWithNumber([]byte(str), &res.Value)
res.Err = serialize.JSON.UnmarshalWithNumber([]byte(str), &res.Value)
return res
}
@ -508,11 +535,11 @@ func (str String) ToObject() ObjectResult {
// Author : go_developer@163.com<白茶清欢>
//
// Date : 18:38 2023/5/4
func (str String) ToStruct(receiver interface{}) error {
func (str String) ToStruct(receiver any) error {
if nil == receiver {
return errors.New("receiver is nil")
}
return util.JSON.UnmarshalWithNumber([]byte(str), receiver)
return serialize.JSON.UnmarshalWithNumber([]byte(str), receiver)
}
// ToInt8Slice ...
@ -527,7 +554,7 @@ func (str String) ToInt8Slice(splitChar ...string) Int8SliceResult {
}
isSplit := len(splitChar) > 0
if !isSplit {
result.Err = util.JSON.UnmarshalWithNumber([]byte(str), &result.Value)
result.Err = serialize.JSON.UnmarshalWithNumber([]byte(str), &result.Value)
return result
}
var (
@ -561,7 +588,7 @@ func (str String) ToInt16Slice(splitChar ...string) Int16SliceResult {
isSplit := len(splitChar) > 0
if !isSplit {
result.Err = util.JSON.UnmarshalWithNumber([]byte(str), &result.Value)
result.Err = serialize.JSON.UnmarshalWithNumber([]byte(str), &result.Value)
return result
}
res := make([]int16, 0)
@ -591,7 +618,7 @@ func (str String) ToInt32Slice(splitChar ...string) Int32SliceResult {
isSplit := len(splitChar) > 0
if !isSplit {
result.Err = util.JSON.UnmarshalWithNumber([]byte(str), &result.Value)
result.Err = serialize.JSON.UnmarshalWithNumber([]byte(str), &result.Value)
return result
}
res := make([]int32, 0)
@ -621,7 +648,7 @@ func (str String) ToInt64Slice(splitChar ...string) Int64SliceResult {
isSplit := len(splitChar) > 0
if !isSplit {
result.Err = util.JSON.UnmarshalWithNumber([]byte(str), &result.Value)
result.Err = serialize.JSON.UnmarshalWithNumber([]byte(str), &result.Value)
return result
}
res := make([]int64, 0)
@ -650,7 +677,7 @@ func (str String) ToIntSlice(splitChar ...string) IntSliceResult {
isSplit := len(splitChar) > 0
if !isSplit {
result.Err = util.JSON.UnmarshalWithNumber([]byte(str), &result.Value)
result.Err = serialize.JSON.UnmarshalWithNumber([]byte(str), &result.Value)
return result
}
res := make([]int, 0)
@ -680,7 +707,7 @@ func (str String) ToUint8Slice(splitChar ...string) Uint8SliceResult {
isSplit := len(splitChar) > 0
if !isSplit {
result.Err = util.JSON.UnmarshalWithNumber([]byte(str), &result.Value)
result.Err = serialize.JSON.UnmarshalWithNumber([]byte(str), &result.Value)
return result
}
res := make([]uint8, 0)
@ -710,7 +737,7 @@ func (str String) ToUint16Slice(splitChar ...string) Uint16SliceResult {
isSplit := len(splitChar) > 0
if !isSplit {
result.Err = util.JSON.UnmarshalWithNumber([]byte(str), &result.Value)
result.Err = serialize.JSON.UnmarshalWithNumber([]byte(str), &result.Value)
return result
}
res := make([]uint16, 0)
@ -740,7 +767,7 @@ func (str String) ToUint32Slice(splitChar ...string) Uint32SliceResult {
isSplit := len(splitChar) > 0
if !isSplit {
result.Err = util.JSON.UnmarshalWithNumber([]byte(str), &result.Value)
result.Err = serialize.JSON.UnmarshalWithNumber([]byte(str), &result.Value)
return result
}
res := make([]uint32, 0)
@ -770,7 +797,7 @@ func (str String) ToUint64Slice(splitChar ...string) Uint64SliceResult {
isSplit := len(splitChar) > 0
if !isSplit {
result.Err = util.JSON.UnmarshalWithNumber([]byte(str), &result.Value)
result.Err = serialize.JSON.UnmarshalWithNumber([]byte(str), &result.Value)
return result
}
res := make([]uint64, 0)
@ -799,7 +826,7 @@ func (str String) ToUintSlice(splitChar ...string) UintSliceResult {
isSplit := len(splitChar) > 0
if !isSplit {
result.Err = util.JSON.UnmarshalWithNumber([]byte(str), &result.Value)
result.Err = serialize.JSON.UnmarshalWithNumber([]byte(str), &result.Value)
return result
}
res := make([]uint, 0)
@ -829,7 +856,7 @@ func (str String) ToBoolSlice(splitChar ...string) BoolSliceResult {
isSplit := len(splitChar) > 0
if !isSplit {
result.Err = util.JSON.UnmarshalWithNumber([]byte(str), &result.Value)
result.Err = serialize.JSON.UnmarshalWithNumber([]byte(str), &result.Value)
return result
}
res := make([]bool, 0)
@ -859,7 +886,7 @@ func (str String) ToFloat32Slice(splitChar ...string) Float32SliceResult {
isSplit := len(splitChar) > 0
if !isSplit {
result.Err = util.JSON.UnmarshalWithNumber([]byte(str), &result.Value)
result.Err = serialize.JSON.UnmarshalWithNumber([]byte(str), &result.Value)
return result
}
res := make([]float32, 0)
@ -888,7 +915,7 @@ func (str String) ToFloat64Slice(splitChar ...string) Float64SliceResult {
isSplit := len(splitChar) > 0
if !isSplit {
result.Err = util.JSON.UnmarshalWithNumber([]byte(str), &result.Value)
result.Err = serialize.JSON.UnmarshalWithNumber([]byte(str), &result.Value)
return result
}
res := make([]float64, 0)
@ -923,6 +950,22 @@ func (str String) ToNumberSlice(splitChar ...string) Float64SliceResult {
return str.ToFloat64Slice(splitChar...)
}
// ToDuration 转换为时间格式
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 20:31 2023/9/4
func (str String) ToDuration(timeUnit time.Duration) DurationResult {
int64Val := str.ToInt64()
if nil != int64Val.Err {
return DurationResult{
Value: 0,
Err: int64Val.Err,
}
}
return Int(int64Val.Value).ToDuration(timeUnit)
}
// ToStringSlice ...
//
// Author : go_developer@163.com<白茶清欢>
@ -936,7 +979,7 @@ func (str String) ToStringSlice(splitChar ...string) StringSliceResult {
isSplit := len(splitChar) > 0
if !isSplit {
result.Err = util.JSON.UnmarshalWithNumber([]byte(str), &result.Value)
result.Err = serialize.JSON.UnmarshalWithNumber([]byte(str), &result.Value)
return result
}
result.Value = strings.Split(string(str), splitChar[0])
@ -948,13 +991,34 @@ func (str String) ToStringSlice(splitChar ...string) StringSliceResult {
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:01 2023/5/5
func (str String) ToAnySlice() AnySliceResult {
func (str String) ToAnySlice(splitCharList ...string) AnySliceResult {
result := AnySliceResult{
Value: []interface{}{},
Value: []any{},
Err: nil,
}
result.Err = util.JSON.UnmarshalWithNumber([]byte(str), &result.Value)
if len(splitCharList) == 0 {
result.Err = serialize.JSON.UnmarshalWithNumber([]byte(str), &result.Value)
return result
}
valArr := strings.Split(str.Value(), splitCharList[0])
valList := make([]any, 0)
for _, item := range valArr {
v := String(item)
if res := v.ToInt64(); nil == res.Err {
valList = append(valList, res.Value)
} else if res := v.ToUint64(); nil == res.Err {
valList = append(valList, res.Value)
} else if res := v.ToFloat64(); nil == res.Err {
valList = append(valList, res.Value)
} else if res := v.ToBool(); nil == res.Err {
valList = append(valList, res.Value)
} else {
valList = append(valList, item)
}
}
result.Value = valList
return result
}
@ -973,7 +1037,7 @@ func (str String) Md5() StringResult {
}
}
return StringResult{
Value: string(h.Sum(nil)),
Value: hex.EncodeToString(h.Sum(nil)),
Err: nil,
}
}
@ -986,3 +1050,141 @@ func (str String) Md5() StringResult {
func (str String) Value() string {
return string(str)
}
// GetLetterList 获取字母列表
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:53 2023/8/11
func (str String) GetLetterList() []string {
return []string{
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
"o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
}
}
// SnakeCaseToCamel 蛇形字符串转换为驼峰
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 4:58 下午 2021/10/25
func (str String) SnakeCaseToCamel() string {
if len(str) == 0 {
return ""
}
builder := strings.Builder{}
index := 0
if str[0] >= 'a' && str[0] <= 'z' {
builder.WriteByte(str[0] - ('a' - 'A'))
index = 1
}
for i := index; i < len(str); i++ {
if str[i] == '_' && i+1 < len(str) {
if str[i+1] >= 'a' && str[i+1] <= 'z' {
builder.WriteByte(str[i+1] - ('a' - 'A'))
i++
continue
}
}
// 将ID转为大写
if str[i] == 'd' && i-1 >= 0 && (str[i-1] == 'i' || str[i-1] == 'I') && (i+1 == len(str) || i+1 < len(str) && str[i+1] == '_') {
builder.WriteByte('d' - ('a' - 'A'))
continue
}
builder.WriteByte(str[i])
}
return builder.String()
}
// Convert 字符串编码转换
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:38 2022/7/9
func (str String) Convert(sourceCode string, targetCode string) String {
sourceCoder := mahonia.NewDecoder(sourceCode)
sourceResult := sourceCoder.ConvertString(str.Value())
targetCoder := mahonia.NewDecoder(targetCode)
_, cdata, _ := targetCoder.Translate([]byte(sourceResult), true)
return String(string(cdata))
}
// ClearChar 清理指定字符
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:59 2023/8/11
func (str String) ClearChar(charList ...string) String {
if len(charList) == 0 {
return str
}
formatStr := str.Value()
for _, item := range charList {
formatStr = strings.ReplaceAll(formatStr, item, "")
}
return String(formatStr)
}
// ReplaceChineseChar 替换常见的中文符号
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:59 2023/4/4
func (str String) ReplaceChineseChar() String {
charTable := map[string]string{
"": "(",
"": ")",
"": ":",
"": ",",
"。": ".",
"【": "]",
"】": "]",
}
return str.ReplaceChar(charTable)
}
// ReplaceChar 替换指定字符
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:01 2023/8/11
func (str String) ReplaceChar(charTable map[string]string) String {
if len(charTable) == 0 {
return str
}
formatStr := str.Value()
for k, v := range charTable {
formatStr = strings.ReplaceAll(formatStr, k, v)
}
return String(formatStr)
}
// HasSubStr 是否包含指定的子串
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 18:37 2024/4/19
func (str String) HasSubStr(subStrList []string) bool {
if len(subStrList) == 0 {
return true
}
v := str.Value()
for _, item := range subStrList {
if strings.Contains(v, item) {
return true
}
}
return false
}
// HashNumber ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:05 2024/6/27
func (str String) HashNumber() Uint64Result {
return Uint64Result{
Value: murmur3.Sum64([]byte(str.Value())),
Err: nil,
}
}

View File

@ -23,3 +23,9 @@ func TestString_ToFloat32(t *testing.T) {
fmt.Println(str.ToInt())
fmt.Println(str.ToUint())
}
func TestString_ToAnySlice(t *testing.T) {
str := "1,2,3"
r := String(str).ToAnySlice(",")
fmt.Println(r)
}

View File

@ -17,7 +17,7 @@ import (
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:07 2023/8/10
func NewStruct(data interface{}) *Struct {
func NewStruct(data any) *Struct {
s, _ := NewStructWithError(data)
return s
}
@ -27,7 +27,7 @@ func NewStruct(data interface{}) *Struct {
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:17 2023/8/10
func NewStructWithError(data interface{}) (*Struct, error) {
func NewStructWithError(data any) (*Struct, error) {
if data == nil {
return nil, errors.New("input data is nil")
}
@ -47,7 +47,7 @@ func NewStructWithError(data interface{}) (*Struct, error) {
//
// Date : 16:05 2023/8/10
type Struct struct {
data interface{}
data any
}
// ToMap 转为Map
@ -58,7 +58,7 @@ type Struct struct {
func (s *Struct) ToMap() MapResult {
if nil == s.data {
return MapResult{
Value: EasyMap(map[interface{}]interface{}{}),
Value: EasyMap(map[any]any{}),
Err: nil,
}
}

157
ternary_operator.go Normal file
View File

@ -0,0 +1,157 @@
// Package wrapper ...
//
// Description : wrapper ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2023-11-28 16:05
package wrapper
var (
// TernaryOperator 三元运算符操作实例
TernaryOperator = &ternaryOperator{}
)
// ternaryOperator ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:06 2023/11/28
type ternaryOperator struct {
}
// CondFunc ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:10 2023/11/28
type CondFunc func() bool
// defaultCondFunc ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:11 2023/11/28
func defaultCondFunc() bool {
return false
}
// Int ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:10 2023/11/28
func (to *ternaryOperator) Int(cond bool, trueVal Int, falseVal Int) Int {
if cond {
return trueVal
}
return falseVal
}
// IntWithFunc ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:11 2023/11/28
func (to *ternaryOperator) IntWithFunc(condFunc CondFunc, trueVal Int, falseVal Int) Int {
if nil == condFunc {
condFunc = defaultCondFunc
}
return to.Int(condFunc(), trueVal, falseVal)
}
// Float ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:10 2023/11/28
func (to *ternaryOperator) Float(cond bool, trueVal Float, falseVal Float) Float {
if cond {
return trueVal
}
return falseVal
}
// FloatWithFunc ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:13 2023/11/28
func (to *ternaryOperator) FloatWithFunc(condFunc CondFunc, trueVal Float, falseVal Float) Float {
if nil == condFunc {
condFunc = defaultCondFunc
}
return to.Float(condFunc(), trueVal, falseVal)
}
// String ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:15 2023/11/28
func (to *ternaryOperator) String(cond bool, trueVal String, falseVal String) String {
if cond {
return trueVal
}
return falseVal
}
// StringWithFunc ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:15 2023/11/28
func (to *ternaryOperator) StringWithFunc(condFunc CondFunc, trueVal String, falseVal String) String {
if nil == condFunc {
condFunc = defaultCondFunc
}
return to.String(condFunc(), trueVal, falseVal)
}
// Map ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:25 2023/11/28
func (to *ternaryOperator) Map(cond bool, trueVal Map, falseVal Map) Map {
if cond {
return trueVal
}
return falseVal
}
// MapWithFunc ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:24 2023/11/28
func (to *ternaryOperator) MapWithFunc(condFunc CondFunc, trueVal Map, falseVal Map) Map {
if nil == condFunc {
condFunc = defaultCondFunc
}
return falseVal
}
// Any ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:26 2023/11/28
func (to *ternaryOperator) Any(cond bool, trueVal *AnyType, falseVal *AnyType) *AnyType {
if cond {
return trueVal
}
return falseVal
}
// AnyWithFunc ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:24 2023/11/28
func (to *ternaryOperator) AnyWithFunc(condFunc CondFunc, trueVal *AnyType, falseVal *AnyType) *AnyType {
if nil == condFunc {
condFunc = defaultCondFunc
}
return to.Any(condFunc(), trueVal, falseVal)
}

245
tool/define/diff.go Normal file
View File

@ -0,0 +1,245 @@
// Package define ...
//
// Description : define ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2024-03-08 11:04
package define
import (
"fmt"
"git.zhangdeman.cn/zhangdeman/util"
"git.zhangdeman.cn/zhangdeman/wrapper"
"reflect"
"strings"
)
// DiffOption 做数据对比时的选项
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:12 2024/3/8
type DiffOption struct {
StrictMode bool `json:"strict_mode"` // 采用严格模式: 1 != 1.0 , 采用非严格模式 1 == 1.0
AllowStringNumber bool `json:"allow_string_number"` // 是否允许字符串数字, 在非严格模式下, 若允许, 则 1 == "1" , 不允许, 则 1 != "1"
IgnoreNotFoundField bool `json:"ignore_not_found_field"` // 忽略不存在的字段
IgnoreEmptyString bool `json:"ignore_empty_string"` // 忽略空字符串, 若输入值为空字符串, 则不做比较, 认为两个值相同
IgnoreZeroNumber bool `json:"ignore_zero_number"` // 忽略置为0的数字, 若输入的数据为数字类型, 则不做比较, 认为两个值相同
IgnoreNil bool `json:"ignore_nil"` // 忽略 nil 值, 若输入值为NIL , 则不做比较, 认为两个值相同
CustomDiffFuncTable map[string]CustomDiffFunc `json:"-"` // 外部自定义的字段是否相同的比较函数, 会优先使用外部输入的比较函数
}
// NewDiffOption ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:06 2024/3/8
func NewDiffOption() *DiffOption {
return &DiffOption{
StrictMode: false,
IgnoreNotFoundField: false,
IgnoreEmptyString: false,
IgnoreZeroNumber: false,
IgnoreNil: false,
CustomDiffFuncTable: make(map[string]CustomDiffFunc),
}
}
// CustomDiffFunc 自定义字段对比方法
//
// 输入分别如下:
//
// field : 要对比的字段
//
// inputVal : 输入的原始数据
//
// storageVal : 当前存储的数据
//
// option : 对比时的额外选项
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:06 2024/3/8
type CustomDiffFunc func(field string, inputVal wrapper.Map, storageVal wrapper.Map, option *DiffOption) *DiffResult
// DiffResult 对比结果
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:10 2024/3/8
type DiffResult struct {
Field string `json:"field"` // 字段名
OldVal any `json:"old_val"` // 当前field在storageVal中的值
NewVal any `json:"new_val"` // 当前field在inputVal中的值
IsSame bool `json:"is_same"` // 两个值是否相同
DiffReason string `json:"diff_reason"` // 两个值不同的原因
Err error `json:"err"` // 对比过程中是否出现异常
}
const (
DiffReasonTypeNotMatch = "TYPE_NOT_MATCH" // 类型不匹配
DiffReasonValueNotMatch = "VALUE_NOT_MATCH" // 数据值不匹配
DiffReasonInputFieldNotFound = "INPUT_FIELD_NOT_FOUND" // 输入数据中不存在相关字段
DiffReasonStorageFieldNotFound = "STORAGE_FIELD_NOT_FOUND" // 存储数据中不存在相关字段
)
var (
// 当前仅支持基础类型的比较不支持slice/map/struct等复杂类型的比较
supportValueTypeTable = map[reflect.Kind]any{
reflect.Bool: true,
reflect.Int: true,
reflect.Int8: true,
reflect.Int16: true,
reflect.Int32: true,
reflect.Int64: true,
reflect.Uint: true,
reflect.Uint8: true,
reflect.Uint16: true,
reflect.Uint32: true,
reflect.Uint64: true,
reflect.Float32: true,
reflect.Float64: true,
reflect.String: true,
// reflect.Ptr: true,
}
)
// IsSupportValueType ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:23 2024/3/8
func IsSupportValueType(kind reflect.Kind) bool {
if _, exist := supportValueTypeTable[kind]; exist {
return true
}
return false
}
// DefaultDiffFunc 默认的diff函数
//
// Author : zhangdeman001@ke.com<张德满>
//
// Date : 12:05 2024/3/8
func DefaultDiffFunc(field string, inputVal wrapper.Map, storageVal wrapper.Map, option *DiffOption) *DiffResult {
if nil == option {
option = NewDiffOption()
}
result := &DiffResult{
Field: field,
OldVal: nil,
NewVal: nil,
IsSame: true,
DiffReason: "",
Err: nil,
}
var (
inputFieldVal any
inputFieldValExist bool
storageFieldVal any
storageFieldValExist bool
)
inputFieldVal, inputFieldValExist = inputVal.Get(field)
storageFieldVal, storageFieldValExist = storageVal.Get(field)
// 字段在输入数据和存储数据中均不存在
if !inputFieldValExist && !storageFieldValExist {
// 输入和存储都没这个字段
return result
}
// 判断输入字段是否存在
if !inputFieldValExist {
if option.IgnoreNotFoundField {
// 忽略不存在的字段
return result
}
// 由于前置逻辑保证了, 输入不存在相关字段, 则现存数据一定存在相关字段
result.IsSame = false
result.DiffReason = DiffReasonInputFieldNotFound
result.OldVal = storageFieldVal
return result
}
// 判断存储字段是否存在
if !storageFieldValExist {
result.IsSame = false
result.DiffReason = DiffReasonStorageFieldNotFound
result.NewVal = inputFieldVal
return result
}
// 校验类型
inputFieldValType := reflect.TypeOf(inputFieldVal)
storageFieldValType := reflect.TypeOf(storageFieldVal)
if inputFieldValType.Kind() == reflect.Ptr {
inputReflect := reflect.ValueOf(inputFieldVal)
inputFieldValType = inputReflect.Type()
inputFieldVal = inputReflect.Interface()
}
if storageFieldValType.Kind() == reflect.Ptr {
storageReflect := reflect.ValueOf(storageFieldValType)
storageFieldValType = storageReflect.Type()
storageFieldVal = storageReflect.Interface()
}
result.NewVal = inputFieldVal
result.OldVal = storageFieldVal
if inputFieldValType.Kind() != storageFieldValType.Kind() && option.StrictMode {
// 严格模式下, 类型不相同
result.IsSame = false
result.DiffReason = DiffReasonTypeNotMatch
return result
}
// 类型相同, 或者非严格模式下不校验类型
if option.StrictMode {
// 严格模式
if inputFieldVal != storageFieldVal {
result.IsSame = false
result.DiffReason = DiffReasonValueNotMatch
return result
}
// return result
}
// 非严格模式
// 存储值尝试转 float64
inputValStr := fmt.Sprintf("%v", inputFieldVal)
storageValStr := fmt.Sprintf("%v", storageFieldVal)
if inputValStr == storageValStr {
return result
}
if option.AllowStringNumber {
// 允许字符串数字
var (
storageFloat64 float64
inputFloat64 float64
)
if err := util.ConvertAssign(&storageFloat64, storageValStr); nil == err {
if err := util.ConvertAssign(&inputFloat64, inputValStr); nil == err {
if storageFloat64 == inputFloat64 {
return result
}
}
}
}
// 浮点型数字. 去小数部分最右侧的0
if inputFieldValType.Kind() == reflect.Float64 || inputFieldValType.Kind() == reflect.Float32 {
inputValStrArr := strings.Split(inputValStr, ".")
if len(inputValStrArr) == 2 {
inputValStrArr[1] = strings.TrimRight(inputValStrArr[1], "0")
inputValStr = strings.Join(inputValStrArr, ".")
}
}
if storageFieldValType.Kind() == reflect.Float64 || storageFieldValType.Kind() == reflect.Float32 {
storageValStrArr := strings.Split(storageValStr, ".")
if len(storageValStrArr) == 2 {
storageValStrArr[1] = strings.TrimRight(storageValStrArr[1], "0")
storageValStr = strings.Join(storageValStrArr, ".")
}
}
if inputValStr != storageValStr {
result.IsSame = false
result.DiffReason = DiffReasonValueNotMatch
return result
}
return result
}

49
tool/define/diff_test.go Normal file
View File

@ -0,0 +1,49 @@
// Package define ...
//
// Description : define ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2024-03-08 15:24
package define
import (
"git.zhangdeman.cn/zhangdeman/wrapper"
"github.com/stretchr/testify/assert"
"testing"
)
func TestDefaultDiffFunc(t *testing.T) {
var (
num1 float64 = 1.0
num2 float32 = 1.00
num3 string = "1"
num4 string = "1.00"
)
input := wrapper.EasyMap(map[string]any{
"num": num1,
"num3": num3,
"num4": num4,
"num5": num1,
})
storage := wrapper.EasyMap(map[string]any{
"num": num2,
"num3": num2,
"num4": num2,
"num5": num1,
})
diffOption := NewDiffOption()
diffOption.StrictMode = true
res := DefaultDiffFunc("num", input, storage, diffOption)
assert.EqualValues(t, false, res.IsSame, "严格模式下, float32与float64不相等")
res = DefaultDiffFunc("num5", input, storage, diffOption)
assert.EqualValues(t, true, res.IsSame, "严格模式下, float32与float32相等")
diffOption.StrictMode = false
res = DefaultDiffFunc("num", input, storage, diffOption)
assert.EqualValues(t, true, res.IsSame, "非严格模式下, float32与float64相等")
res = DefaultDiffFunc("num3", input, storage, diffOption)
assert.EqualValues(t, true, res.IsSame, "非严格模式下, float32与string相等")
diffOption.AllowStringNumber = true
res = DefaultDiffFunc("num4", input, storage, diffOption)
assert.EqualValues(t, true, res.IsSame, "非严格模式下, float32与string相等")
}

15
tool/define/version.go Normal file
View File

@ -0,0 +1,15 @@
// Package define ...
//
// Description : define ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2023-12-27 17:08
package define
const (
VersionCompareFail = -2 // 版本比较失败
VersionOneMax = -1 // 第一个版本号大
VersionEqual = 0 // 两个版本号相等
VersionTwoMax = 1 // 第二个版本号大
)

68
tool/diff.go Normal file
View File

@ -0,0 +1,68 @@
// Package tool ...
//
// Description : 对比两个数据是否相同 + 构建不同数据的前后值
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2024-03-08 11:03
package tool
import (
"git.zhangdeman.cn/zhangdeman/wrapper"
"git.zhangdeman.cn/zhangdeman/wrapper/tool/define"
)
var (
Diff = &diff{}
)
type diff struct {
}
// Compare 比较两个数据源的指定字段
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:53 2024/3/8
func (d *diff) Compare(fieldList []string, input wrapper.Map, storage wrapper.Map, option *define.DiffOption) map[string]*define.DiffResult {
if nil == option {
option = define.NewDiffOption()
}
res := make(map[string]*define.DiffResult)
for _, itemField := range fieldList {
res[itemField] = d.CompareSingle(itemField, input, storage, option)
}
return res
}
// CompareSingle 比较一个字段
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:57 2024/3/8
func (d *diff) CompareSingle(field string, input wrapper.Map, storage wrapper.Map, option *define.DiffOption) *define.DiffResult {
if nil == option {
option = define.NewDiffOption()
}
if compareFunc, exist := option.CustomDiffFuncTable[field]; exist && nil != compareFunc {
return compareFunc(field, input, storage, option)
} else {
return define.DefaultDiffFunc(field, input, storage, option)
}
}
// IsSame 判断连个数据是否一致
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:16 2024/3/11
func (d *diff) IsSame(fieldList []string, input wrapper.Map, storage wrapper.Map, option *define.DiffOption) bool {
res := d.Compare(fieldList, input, storage, option)
for _, item := range res {
if item.IsSame {
continue
}
return false
}
return true
}

98
tool/version.go Normal file
View File

@ -0,0 +1,98 @@
// Package tool ...
//
// Description : util ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2023-12-27 17:06
package tool
import (
"git.zhangdeman.cn/zhangdeman/wrapper"
"git.zhangdeman.cn/zhangdeman/wrapper/tool/define"
)
var (
Version = &version{}
)
type version struct {
}
// getVersionArr 解析版本号
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:42 2023/12/27
func (v *version) getVersionArr(versionOne string, versionTwo string) ([]int64, []int64, error) {
oneWrapper := wrapper.String(versionOne).ToInt64Slice(".")
twoWrapper := wrapper.String(versionTwo).ToInt64Slice(".")
if oneWrapper.Err != nil {
return nil, nil, oneWrapper.Err
}
if twoWrapper.Err != nil {
return nil, nil, twoWrapper.Err
}
return oneWrapper.Value, twoWrapper.Value, nil
}
// Compare 比较版本号的大小, 版本号格式必须是 x.y.z 的形式,几个 . 不限制, x、y、z 必须是是数字
//
// strictMode 严格模式, 非严格模式下, 2.4 == 2.4.0 , 开启严格模式, 则认为 2.4 < 2.4.0 , 因为 2.4 没有小版本号
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:07 2023/12/27
func (v *version) Compare(versionOne string, versionTwo string, strictMode bool) (int, error) {
oneVersionArr, twoVersionArr, err := v.getVersionArr(versionOne, versionTwo)
if nil != err {
return define.VersionCompareFail, err
}
oneVersionLength := len(oneVersionArr)
twoVersionLength := len(twoVersionArr)
// 版本号长度不一致补位
if oneVersionLength > twoVersionLength {
for fill := 0; fill < oneVersionLength-twoVersionLength; fill++ {
twoVersionArr = append(twoVersionArr, 0)
}
}
if oneVersionLength < twoVersionLength {
for fill := 0; fill < twoVersionLength-oneVersionLength; fill++ {
oneVersionArr = append(oneVersionArr, 0)
}
}
// 开始比较
for offset := 0; offset < len(oneVersionArr); offset++ {
if oneVersionArr[offset] == twoVersionArr[offset] {
// 当前位版本相等
continue
}
if oneVersionArr[offset] > twoVersionArr[offset] {
// 第一个版本号大
return define.VersionOneMax, nil
} else {
// 第二个版本号大
return define.VersionTwoMax, nil
}
}
// 版本号一致, 判断严格模式与非严格模式
if !strictMode || oneVersionLength == twoVersionLength {
return define.VersionEqual, nil
}
return wrapper.TernaryOperator.Int(
oneVersionLength > twoVersionLength,
wrapper.Int(define.VersionOneMax),
wrapper.Int(define.VersionTwoMax),
).ToInt().Value, nil
}
// CompareIgnoreError 忽略error
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 18:20 2023/12/27
func (v *version) CompareIgnoreError(versionOne string, versionTwo string, strictMode bool) int {
res, _ := v.Compare(versionOne, versionTwo, strictMode)
return res
}

22
tool/version_test.go Normal file
View File

@ -0,0 +1,22 @@
// Package tool ...
//
// Description : tool ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2023-12-27 17:51
package tool
import (
"fmt"
"testing"
)
func Test_version_Compare(t *testing.T) {
fmt.Println(Version.Compare("2.4.1", "2.4.1.0", true))
fmt.Println(Version.Compare("2.4.1", "2.4.1.0", false))
fmt.Println(Version.Compare("2.4.0", "2.4.1", true))
fmt.Println(Version.Compare("2.4.2", "2.4.1", true))
fmt.Println(Version.Compare("2.4", "2.4.1", true))
fmt.Println(Version.Compare("2.4.2", "2.4", true))
}

35
try/abstract.go Normal file
View File

@ -0,0 +1,35 @@
// Package try ...
//
// Description : try ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2023-07-20 11:26
package try
// ICatchHandler 异常处理器接口约束
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:26 2023/7/20
type ICatchHandler interface {
Catch(errCode string, handler func(errCode string, data map[string]any)) ICatchHandler
CatchAll(handler func(errCode string, data map[string]any)) IFinalHandler
IFinalHandler
}
// IFinalHandler 所有异常 / 逻辑执行成功之后的逻辑
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:27 2023/7/20
type IFinalHandler interface {
Finally(data map[string]any, handlers ...func(data map[string]any))
}
// ILogicFunction 逻辑函数约束
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:29 2023/7/20
type ILogicFunction func(input *LogicFuncInput) LogicFuncOutput

95
try/default.go Normal file
View File

@ -0,0 +1,95 @@
// Package try ...
//
// Description : try ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2023-07-20 12:13
package try
// DefaultCatchHandler catch handler默认实现
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:14 2023/7/20
type DefaultCatchHandler struct {
hasDeal bool // 异常是否已被处理
errCode string
data map[string]any
}
// hasDealError 判断异常是否已经被处理
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:46 2023/7/20
func (d *DefaultCatchHandler) hasDealError() bool {
if d.hasDeal {
return true
}
if d.errCode == "" {
return true
}
return false
}
// Catch 处理指定errorCode
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:19 2023/7/20
func (d *DefaultCatchHandler) Catch(errCode string, handler func(errCode string, data map[string]any)) ICatchHandler {
if d.hasDealError() {
return d
}
if errCode != d.errCode {
return d
}
d.hasDeal = true
defer func() {
if r := recover(); nil != r {
d.hasDeal = false
d.data[errCode+"_handler_error"] = r.(error).Error()
}
}()
handler(d.errCode, d.data)
return d
}
// CatchAll 捕捉任意一场
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:47 2023/7/20
func (d *DefaultCatchHandler) CatchAll(handler func(errCode string, data map[string]any)) IFinalHandler {
if d.hasDealError() {
return d
}
defer func() {
if r := recover(); nil != r {
d.data[d.errCode+"_handler_error"] = r.(error).Error()
}
}()
d.hasDeal = true
handler(d.errCode, d.data)
return d
}
// Finally 最终逻辑
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:48 2023/7/20
func (d *DefaultCatchHandler) Finally(data map[string]any, handlers ...func(data map[string]any)) {
if data == nil {
data = map[string]any{}
}
defer func() {
if r := recover(); nil != r {
}
}()
for _, itemHandler := range handlers {
itemHandler(data)
}
}

50
try/define.go Normal file
View File

@ -0,0 +1,50 @@
// Package try ...
//
// Description : try ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2023-07-20 11:29
package try
// LogicFuncInput 逻辑函数输入参数
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:30 2023/7/20
type LogicFuncInput struct {
Parameter map[string]any
}
// LogicFuncOutput ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:30 2023/7/20
type LogicFuncOutput struct {
ErrCode string // 错误标识码
Data map[string]any // 错误时返回的数据
}
// NewLogicFuncOutput 获取逻辑函数输出数据
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:33 2023/7/20
func NewLogicFuncOutput(code string, data map[string]any) LogicFuncOutput {
if data == nil {
data = map[string]any{}
}
r := LogicFuncOutput{
ErrCode: code,
Data: data,
}
return r
}
const (
// NilLogicFunc 。。。
NilLogicFunc = "NIL_LOGIC_FUNC"
// LogicFuncPanic ...
LogicFuncPanic = "LOGIC_FUNC_PANIC"
)

41
try/try.go Normal file
View File

@ -0,0 +1,41 @@
// Package try ...
//
// Description : try ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2023-07-20 11:36
package try
// Try try入口函数
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:37 2023/7/20
func Try(fn ILogicFunction, input *LogicFuncInput) ICatchHandler {
catchHandler := &DefaultCatchHandler{}
if nil == fn {
// 逻辑函数空指针
catchHandler.errCode = NilLogicFunc
return catchHandler
}
defer func() {
if r := recover(); r != nil {
catchHandler.errCode = LogicFuncPanic
catchHandler.data = map[string]any{
"message": r.(error).Error(),
}
}
}()
if nil == input {
input = &LogicFuncInput{
Parameter: map[string]any{},
}
}
result := fn(input)
catchHandler.errCode = result.ErrCode
catchHandler.data = result.Data
return catchHandler
}