4 Commits

8 changed files with 247 additions and 78 deletions

7
any.go
View File

@ -43,7 +43,10 @@ type AnyType struct {
// //
// Date : 18:21 2023/6/1 // Date : 18:21 2023/6/1
func (at *AnyType) IsNil() bool { func (at *AnyType) IsNil() bool {
return at.data == nil if at.data == nil {
return true
}
return reflect.ValueOf(at.data).IsNil()
} }
// Type 获取类型 // Type 获取类型
@ -97,7 +100,7 @@ func (at *AnyType) ToString() String {
case consts.DataTypeSliceAny: case consts.DataTypeSliceAny:
var val []any var val []any
_ = serialize.JSON.Transition(at.data, &val) _ = serialize.JSON.Transition(at.data, &val)
return String(ArrayType[any, any](val).ToString().Value) return String(ArrayType[any](val).ToString().Value)
case consts.DataTypeMapAnyAny: case consts.DataTypeMapAnyAny:
return String(EasyMap(at.data).ToString()) return String(EasyMap(at.data).ToString())
case consts.DataTypeInt: case consts.DataTypeInt:

View File

@ -9,9 +9,7 @@ package wrapper
import ( import (
"encoding/json" "encoding/json"
"errors"
"git.zhangdeman.cn/zhangdeman/op_type" "git.zhangdeman.cn/zhangdeman/op_type"
"github.com/tidwall/gjson"
"reflect" "reflect"
"strings" "strings"
) )
@ -21,8 +19,8 @@ import (
// Author : go_developer@163.com<白茶清欢> // Author : go_developer@163.com<白茶清欢>
// //
// Date : 21:03 2023/6/11 // Date : 21:03 2023/6/11
func ArrayType[Bt op_type.BaseType, ExtractDataType op_type.BaseType](value []Bt) *Array[Bt, ExtractDataType] { func ArrayType[Bt op_type.BaseType](value []Bt) *Array[Bt] {
at := &Array[Bt, ExtractDataType]{ at := &Array[Bt]{
value: value, value: value,
} }
return at return at
@ -33,7 +31,7 @@ func ArrayType[Bt op_type.BaseType, ExtractDataType op_type.BaseType](value []Bt
// Author : go_developer@163.com<白茶清欢> // Author : go_developer@163.com<白茶清欢>
// //
// Date : 21:05 2023/6/11 // Date : 21:05 2023/6/11
type Array[Bt op_type.BaseType, ExtractDataType op_type.BaseType] struct { type Array[Bt op_type.BaseType] struct {
value []Bt value []Bt
convertErr error convertErr error
itemType reflect.Kind // 简单list场景下, 每一项的数据类型 itemType reflect.Kind // 简单list场景下, 每一项的数据类型
@ -44,7 +42,7 @@ type Array[Bt op_type.BaseType, ExtractDataType op_type.BaseType] struct {
// Author : go_developer@163.com<白茶清欢> // Author : go_developer@163.com<白茶清欢>
// //
// Date : 21:11 2023/6/11 // Date : 21:11 2023/6/11
func (at *Array[Bt, ExtractDataType]) IsNil() bool { func (at *Array[Bt]) IsNil() bool {
return at.value == nil return at.value == nil
} }
@ -53,7 +51,7 @@ func (at *Array[Bt, ExtractDataType]) IsNil() bool {
// Author : go_developer@163.com<白茶清欢> // Author : go_developer@163.com<白茶清欢>
// //
// Date : 11:42 2024/4/22 // Date : 11:42 2024/4/22
func (at *Array[Bt, ExtractDataType]) ToStringSlice() []string { func (at *Array[Bt]) ToStringSlice() []string {
list := make([]string, 0) list := make([]string, 0)
for _, item := range at.value { for _, item := range at.value {
byteData, _ := json.Marshal(item) byteData, _ := json.Marshal(item)
@ -67,7 +65,7 @@ func (at *Array[Bt, ExtractDataType]) ToStringSlice() []string {
// Author : go_developer@163.com<白茶清欢> // Author : go_developer@163.com<白茶清欢>
// //
// Date : 17:43 2023/6/12 // Date : 17:43 2023/6/12
func (at *Array[Bt, ExtractDataType]) Unique() []Bt { func (at *Array[Bt]) Unique() []Bt {
result := make([]Bt, 0) result := make([]Bt, 0)
dataTable := make(map[string]bool) dataTable := make(map[string]bool)
@ -92,7 +90,7 @@ func (at *Array[Bt, ExtractDataType]) Unique() []Bt {
// Author : go_developer@163.com<白茶清欢> // Author : go_developer@163.com<白茶清欢>
// //
// Date : 16:28 2023/7/31 // Date : 16:28 2023/7/31
func (at *Array[Bt, ExtractDataType]) Has(input Bt) int { func (at *Array[Bt]) Has(input Bt) int {
for idx := 0; idx < len(at.value); idx++ { for idx := 0; idx < len(at.value); idx++ {
if reflect.TypeOf(at.value[idx]).String() != reflect.TypeOf(input).String() { if reflect.TypeOf(at.value[idx]).String() != reflect.TypeOf(input).String() {
// 类型不同 // 类型不同
@ -113,7 +111,7 @@ func (at *Array[Bt, ExtractDataType]) Has(input Bt) int {
// Author : go_developer@163.com<白茶清欢> // Author : go_developer@163.com<白茶清欢>
// //
// Date : 16:57 2023/9/28 // Date : 16:57 2023/9/28
func (at *Array[Bt, ExtractDataType]) ToString() StringResult { func (at *Array[Bt]) ToString() StringResult {
if at.IsNil() { if at.IsNil() {
return StringResult{ return StringResult{
Value: "", Value: "",
@ -132,7 +130,7 @@ func (at *Array[Bt, ExtractDataType]) ToString() StringResult {
// Author : go_developer@163.com<白茶清欢> // Author : go_developer@163.com<白茶清欢>
// //
// Date : 17:42 2023/10/25 // Date : 17:42 2023/10/25
func (at *Array[Bt, ExtractDataType]) ToStringWithSplit(split string) StringResult { func (at *Array[Bt]) ToStringWithSplit(split string) StringResult {
if at.IsNil() { if at.IsNil() {
return StringResult{ return StringResult{
Value: "", Value: "",
@ -144,47 +142,3 @@ func (at *Array[Bt, ExtractDataType]) ToStringWithSplit(split string) StringResu
Err: nil, 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

@ -13,24 +13,6 @@ import (
) )
func TestArray_Unique(t *testing.T) { func TestArray_Unique(t *testing.T) {
fmt.Println(ArrayType[any, any]([]any{"1", 1, 1, "1", 2, 3}).Unique()) fmt.Println(ArrayType([]any{"1", 1, 1, "1", 2, 3}).Unique())
fmt.Println(ArrayType[int, any]([]int{1, 1, 2, 3}).Unique()) fmt.Println(ArrayType([]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"))
} }

197
dynamic_struct.go Normal file
View File

@ -0,0 +1,197 @@
// Package wrapper ...
//
// Description : wrapper ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2024-08-21 16:43
package wrapper
import (
"fmt"
"reflect"
)
func NewDynamic() *DynamicStruct {
return &DynamicStruct{
structFieldList: make([]reflect.StructField, 0),
}
}
// DynamicStruct 动态生成数据结构
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:48 2024/8/21
type DynamicStruct struct {
structFieldList []reflect.StructField // 结构体字段列表
}
// AddInt 添加int字段统一Int64
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:50 2024/8/21
func (ds *DynamicStruct) AddInt(fieldName string, fieldTag string, pkgPath string) {
ds.AddStructField(reflect.StructField{
Name: fieldName,
PkgPath: pkgPath,
Type: reflect.TypeOf(int64(0)),
Tag: reflect.StructTag(fmt.Sprintf(`json:"%v"`, fieldTag)),
})
}
// AddUint 添加uint字段, 统一 uint64
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:50 2024/8/21
func (ds *DynamicStruct) AddUint(fieldName string, fieldTag string, pkgPath string) {
ds.AddStructField(reflect.StructField{
Name: fieldName,
PkgPath: pkgPath,
Type: reflect.TypeOf(uint64(0)),
Tag: reflect.StructTag(fieldTag),
})
}
// AddString 添加字符串字段
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:49 2024/8/21
func (ds *DynamicStruct) AddString(fieldName string, fieldTag string, pkgPath string) {
ds.AddStructField(reflect.StructField{
Name: fieldName,
PkgPath: pkgPath,
Type: reflect.TypeOf(""),
Tag: reflect.StructTag(fmt.Sprintf(`json:"%v"`, fieldTag)),
})
}
// AddBool 添加bool字段
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:49 2024/8/21
func (ds *DynamicStruct) AddBool(fieldName string, fieldTag string, pkgPath string) {
ds.AddStructField(reflect.StructField{
Name: fieldName,
PkgPath: pkgPath,
Type: reflect.TypeOf(true),
Tag: reflect.StructTag(fmt.Sprintf(`json:"%v"`, fieldTag)),
})
}
// AddFloat 添加float字段, 统一 float64
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:48 2024/8/21
func (ds *DynamicStruct) AddFloat(fieldName string, fieldTag string, pkgPath string) {
ds.AddStructField(reflect.StructField{
Name: fieldName,
PkgPath: pkgPath,
Type: reflect.TypeOf(float64(0)),
Tag: reflect.StructTag(fmt.Sprintf(`json:"%v"`, fieldTag)),
})
}
// AddSlice 添加slice
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:47 2024/8/21
func (ds *DynamicStruct) AddSlice(fieldName string, fieldTag string, pkgPath string) {
ds.AddStructField(reflect.StructField{
Name: fieldName,
PkgPath: pkgPath,
Type: reflect.TypeOf([]any{}),
Tag: reflect.StructTag(fieldTag),
})
}
// AddMap 添加map字段
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:43 2024/8/21
func (ds *DynamicStruct) AddMap(fieldName string, fieldTag string, pkgPath string) {
ds.AddStructField(reflect.StructField{
Name: fieldName,
PkgPath: pkgPath,
Type: reflect.TypeOf(map[string]any{}),
Tag: reflect.StructTag(fieldTag),
})
}
// AddAny 添加任意类型字段
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:52 2024/8/21
func (ds *DynamicStruct) AddAny(fieldName string, fieldTag string, pkgPath string, value any) {
if nil == value {
// 不能是空指针
return
}
ds.AddStructField(reflect.StructField{
Name: fieldName,
PkgPath: pkgPath,
Type: reflect.TypeOf(value),
Tag: reflect.StructTag(fieldTag),
})
}
// AddStructField 添加结构体字段
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:42 2024/8/21
func (ds *DynamicStruct) AddStructField(field reflect.StructField) {
if field.Tag == "" {
field.Tag = reflect.StructTag(fmt.Sprintf(`json:"%v"`, field.Name))
}
ds.structFieldList = append(ds.structFieldList, field)
}
// GetStructType 获取结构体的类型
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:58 2024/8/21
func (ds *DynamicStruct) GetStructType() reflect.Type {
return reflect.StructOf(ds.structFieldList)
}
// ToStructDefaultValue 获取结构体的值, 并采用对应类型默认值填充相关字段
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:56 2024/8/21
func (ds *DynamicStruct) ToStructDefaultValue() any {
defer ds.Clear()
defaultValue := reflect.New(ds.GetStructType()).Elem().Interface()
return defaultValue
}
// ToStructDefaultSliceValue 自动生成结构体列表
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:04 2024/8/21
func (ds *DynamicStruct) ToStructDefaultSliceValue() any {
defer ds.Clear()
tSlice := reflect.MakeSlice(reflect.SliceOf(ds.GetStructType()), 0, 0)
return reflect.New(tSlice.Type()).Elem().Interface()
}
// Clear 清理
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:08 2024/8/21
func (ds *DynamicStruct) Clear() {
// 清理掉已设置的字段, 不然实例复用会互相影响
ds.structFieldList = make([]reflect.StructField, 0)
}

27
dynamic_struct_test.go Normal file
View File

@ -0,0 +1,27 @@
// Package wrapper ...
//
// Description : wrapper ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2024-08-21 17:56
package wrapper
import (
"fmt"
"github.com/mitchellh/mapstructure"
"testing"
)
func TestNewDynamic(t *testing.T) {
instance := NewDynamic()
instance.AddInt("Age", "age", "")
instance.AddString("Name", "name", "")
defaultVal := instance.ToStructDefaultValue()
testMap := map[string]any{
"name": "白茶",
"age": 18,
}
_ = mapstructure.Decode(testMap, &defaultVal)
fmt.Println(defaultVal)
}

1
go.mod
View File

@ -21,6 +21,7 @@ require (
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-ini/ini v1.67.0 // indirect github.com/go-ini/ini v1.67.0 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mozillazg/go-pinyin v0.20.0 // indirect github.com/mozillazg/go-pinyin v0.20.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/match v1.1.1 // indirect

2
go.sum
View File

@ -38,6 +38,8 @@ 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/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 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mozillazg/go-pinyin v0.20.0 h1:BtR3DsxpApHfKReaPO1fCqF4pThRwH9uwvXzm+GnMFQ= 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/mozillazg/go-pinyin v0.20.0/go.mod h1:iR4EnMMRXkfpFVV5FMi4FNB6wGq9NV6uDWbUuPhP4Yc=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=

View File

@ -71,7 +71,10 @@ func (ot *ObjectType) IsValid() bool {
// //
// Date : 18:50 2023/6/1 // Date : 18:50 2023/6/1
func (ot *ObjectType) IsNil() bool { func (ot *ObjectType) IsNil() bool {
return ot.source == nil if ot.source == nil {
return true
}
return reflect.ValueOf(ot.source).IsNil()
} }
// ToString 转字符串 // ToString 转字符串