Skip to content

Commit 61dc501

Browse files
committed
support case-insensitive copy
1 parent 20cee7e commit 61dc501

File tree

3 files changed

+18
-9
lines changed

3 files changed

+18
-9
lines changed

copier.go

+14-5
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,10 @@ const (
3737
type Option struct {
3838
// setting this value to true will ignore copying zero values of all the fields, including bools, as well as a
3939
// struct having all it's fields set to their zero values respectively (see IsZero() in reflect/value.go)
40-
IgnoreEmpty bool
41-
DeepCopy bool
42-
Converters []TypeConverter
40+
IgnoreEmpty bool
41+
CaseSensitive bool
42+
DeepCopy bool
43+
Converters []TypeConverter
4344
}
4445

4546
func (opt Option) converters() map[converterPair]TypeConverter {
@@ -300,7 +301,7 @@ func copier(toValue interface{}, fromValue interface{}, opt Option) (err error)
300301
break
301302
}
302303

303-
toField := dest.FieldByName(destFieldName)
304+
toField := fieldByName(dest, destFieldName, opt.CaseSensitive)
304305
if toField.IsValid() {
305306
if toField.CanSet() {
306307
isSet, err := set(toField, fromField, opt.DeepCopy, converters)
@@ -346,7 +347,7 @@ func copier(toValue interface{}, fromValue interface{}, opt Option) (err error)
346347
}
347348

348349
if fromMethod.IsValid() && fromMethod.Type().NumIn() == 0 && fromMethod.Type().NumOut() == 1 && !shouldIgnore(fromMethod, opt.IgnoreEmpty) {
349-
if toField := dest.FieldByName(destFieldName); toField.IsValid() && toField.CanSet() {
350+
if toField := fieldByName(dest, destFieldName, opt.CaseSensitive); toField.IsValid() && toField.CanSet() {
350351
values := fromMethod.Call([]reflect.Value{})
351352
if len(values) >= 1 {
352353
set(toField, values[0], opt.DeepCopy, converters)
@@ -741,3 +742,11 @@ func driverValuer(v reflect.Value) (i driver.Valuer, ok bool) {
741742
i, ok = v.Addr().Interface().(driver.Valuer)
742743
return
743744
}
745+
746+
func fieldByName(v reflect.Value, name string, caseSensitive bool) reflect.Value {
747+
if caseSensitive {
748+
return v.FieldByName(name)
749+
}
750+
751+
return v.FieldByNameFunc(func(n string) bool { return strings.EqualFold(n, name) })
752+
}

copier_benchmark_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func BenchmarkNamaCopy(b *testing.B) {
2929
for x := 0; x < b.N; x++ {
3030
employee := &Employee{
3131
Name: user.Name,
32-
Nickname: &user.Nickname,
32+
NickName: &user.Nickname,
3333
Age: int64(user.Age),
3434
FakeAge: int(*user.FakeAge),
3535
DoubleAge: user.DoubleAge(),

copier_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ type Employee struct {
3030
_User *User
3131
Name string
3232
Birthday *time.Time
33-
Nickname *string
33+
NickName *string
3434
Age int64
3535
FakeAge int
3636
EmployeID int64
@@ -48,7 +48,7 @@ func checkEmployee(employee Employee, user User, t *testing.T, testCase string)
4848
if employee.Name != user.Name {
4949
t.Errorf("%v: Name haven't been copied correctly.", testCase)
5050
}
51-
if employee.Nickname == nil || *employee.Nickname != user.Nickname {
51+
if employee.NickName == nil || *employee.NickName != user.Nickname {
5252
t.Errorf("%v: NickName haven't been copied correctly.", testCase)
5353
}
5454
if employee.Birthday == nil && user.Birthday != nil {
@@ -102,7 +102,7 @@ func TestCopySameStructWithPointerField(t *testing.T) {
102102

103103
func checkEmployee2(employee Employee, user *User, t *testing.T, testCase string) {
104104
if user == nil {
105-
if employee.Name != "" || employee.Nickname != nil || employee.Birthday != nil || employee.Age != 0 ||
105+
if employee.Name != "" || employee.NickName != nil || employee.Birthday != nil || employee.Age != 0 ||
106106
employee.DoubleAge != 0 || employee.FakeAge != 0 || employee.SuperRule != "" || employee.Notes != nil {
107107
t.Errorf("%v : employee should be empty", testCase)
108108
}

0 commit comments

Comments
 (0)