feat: copier util

This commit is contained in:
Bobo
2025-05-22 10:33:02 +08:00
parent 2fb73a0a1f
commit d1aa8e36ad
3 changed files with 214 additions and 1 deletions

View File

@@ -41,3 +41,64 @@ var TimestamppbToTimeConverter = copier.TypeConverter{
return timeutil.TimestamppbToTime(src.(*timestamppb.Timestamp)), nil
},
}
func MakeTypeConverter(srcType, dstType interface{}, fn func(src interface{}) (interface{}, error)) copier.TypeConverter {
return copier.TypeConverter{
SrcType: srcType,
DstType: dstType,
Fn: fn,
}
}
func MakeTypeConverterPair(srcType, dstType interface{}, fromFn, toFn func(src interface{}) (interface{}, error)) []copier.TypeConverter {
return []copier.TypeConverter{
{
SrcType: srcType,
DstType: dstType,
Fn: fromFn,
},
{
SrcType: dstType,
DstType: srcType,
Fn: toFn,
},
}
}
func MakeGenericTypeConverterPair[A interface{}, B interface{}](srcType A, dstType B, fromFn func(src A) B, toFn func(src B) A) []copier.TypeConverter {
return []copier.TypeConverter{
{
SrcType: srcType,
DstType: dstType,
Fn: func(src interface{}) (interface{}, error) {
return fromFn(src.(A)), nil
},
},
{
SrcType: dstType,
DstType: srcType,
Fn: func(src interface{}) (interface{}, error) {
return toFn(src.(B)), nil
},
},
}
}
func MakeErrorHandlingTypeConverterPair[A interface{}, B interface{}](srcType A, dstType B, fromFn func(src A) (B, error), toFn func(src B) (A, error)) []copier.TypeConverter {
return []copier.TypeConverter{
{
SrcType: srcType,
DstType: dstType,
Fn: func(src interface{}) (interface{}, error) {
return fromFn(src.(A))
},
},
{
SrcType: dstType,
DstType: srcType,
Fn: func(src interface{}) (interface{}, error) {
return toFn(src.(B))
},
},
}
}

View File

@@ -0,0 +1,152 @@
package copierutil
import (
"testing"
"time"
"github.com/tx7do/go-utils/timeutil"
"github.com/tx7do/go-utils/trans"
)
func TestMakeTypeConverter(t *testing.T) {
srcType := &time.Time{}
dstType := trans.Ptr("")
fn := func(src interface{}) (interface{}, error) {
return timeutil.TimeToTimeString(src.(*time.Time)), nil
}
converter := MakeTypeConverter(srcType, dstType, fn)
// 验证转换器的类型
if converter.SrcType != srcType || converter.DstType != dstType {
t.Errorf("converter types mismatch")
}
// 验证转换器的功能
result, err := converter.Fn(&time.Time{})
if err != nil {
t.Errorf("converter function failed: %v", err)
}
if _, ok := result.(*string); !ok {
t.Errorf("converter result type mismatch")
}
}
func TestMakeTypeConverterPair(t *testing.T) {
srcType := &time.Time{}
dstType := trans.Ptr("")
fromFn := func(src interface{}) (interface{}, error) {
return timeutil.TimeToTimeString(src.(*time.Time)), nil
}
toFn := func(src interface{}) (interface{}, error) {
return timeutil.StringTimeToTime(src.(*string)), nil
}
converters := MakeTypeConverterPair(srcType, dstType, fromFn, toFn)
if len(converters) != 2 {
t.Fatalf("expected 2 converters, got %d", len(converters))
}
// 验证第一个转换器
if converters[0].SrcType != srcType || converters[0].DstType != dstType {
t.Errorf("first converter types mismatch")
}
result, err := converters[0].Fn(&time.Time{})
if err != nil {
t.Errorf("first converter function failed: %v", err)
}
if _, ok := result.(*string); !ok {
t.Errorf("first converter result type mismatch")
}
// 验证第二个转换器
if converters[1].SrcType != dstType || converters[1].DstType != srcType {
t.Errorf("second converter types mismatch")
}
result, err = converters[1].Fn(trans.Ptr(""))
if err != nil {
t.Errorf("second converter function failed: %v", err)
}
if _, ok := result.(*time.Time); !ok {
t.Errorf("second converter result type mismatch")
}
}
func TestMakeGenericTypeConverterPair(t *testing.T) {
srcType := &time.Time{}
dstType := trans.Ptr("")
fromFn := timeutil.TimeToTimeString
toFn := timeutil.StringTimeToTime
converters := MakeGenericTypeConverterPair(srcType, dstType, fromFn, toFn)
if len(converters) != 2 {
t.Fatalf("expected 2 converters, got %d", len(converters))
}
// 验证第一个转换器
if converters[0].SrcType != srcType || converters[0].DstType != dstType {
t.Errorf("first converter types mismatch")
}
result, err := converters[0].Fn(&time.Time{})
if err != nil {
t.Errorf("first converter function failed: %v", err)
}
if _, ok := result.(*string); !ok {
t.Errorf("first converter result type mismatch")
}
// 验证第二个转换器
if converters[1].SrcType != dstType || converters[1].DstType != srcType {
t.Errorf("second converter types mismatch")
}
result, err = converters[1].Fn(trans.Ptr(""))
if err != nil {
t.Errorf("second converter function failed: %v", err)
}
if _, ok := result.(*time.Time); !ok {
t.Errorf("second converter result type mismatch")
}
}
func TestMakeErrorHandlingTypeConverterPair(t *testing.T) {
srcType := &time.Time{}
dstType := trans.Ptr("")
fromFn := func(src *time.Time) (*string, error) {
return timeutil.TimeToTimeString(src), nil
}
toFn := func(src *string) (*time.Time, error) {
return timeutil.StringTimeToTime(src), nil
}
converters := MakeErrorHandlingTypeConverterPair(srcType, dstType, fromFn, toFn)
if len(converters) != 2 {
t.Fatalf("expected 2 converters, got %d", len(converters))
}
// 验证第一个转换器
if converters[0].SrcType != srcType || converters[0].DstType != dstType {
t.Errorf("first converter types mismatch")
}
result, err := converters[0].Fn(&time.Time{})
if err != nil {
t.Errorf("first converter function failed: %v", err)
}
if _, ok := result.(*string); !ok {
t.Errorf("first converter result type mismatch")
}
// 验证第二个转换器
if converters[1].SrcType != dstType || converters[1].DstType != srcType {
t.Errorf("second converter types mismatch")
}
result, err = converters[1].Fn(trans.Ptr(""))
if err != nil {
t.Errorf("second converter function failed: %v", err)
}
if _, ok := result.(*time.Time); !ok {
t.Errorf("second converter result type mismatch")
}
}

View File

@@ -3,7 +3,7 @@ git tag v1.1.22
git tag bank_card/v1.1.5
git tag geoip/v1.1.5
git tag translator/v1.1.2
git tag copierutil/v0.0.1
git tag copierutil/v0.0.2
git tag entgo/v1.1.28
git tag gorm/v1.1.6