-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathutil.go
50 lines (46 loc) · 1.37 KB
/
util.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package deepcopy
import (
"reflect"
)
// structFieldGetWithInit gets deep nested field with init value for pointer ones
func structFieldGetWithInit(field reflect.Value, index []int) reflect.Value {
for _, idx := range index {
if field.Kind() == reflect.Pointer {
if field.IsNil() {
field.Set(reflect.New(field.Type().Elem()))
}
field = field.Elem()
}
field = field.Field(idx)
}
return field
}
// structFieldSetZero sets zero to a deep nested field
func structFieldSetZero(field reflect.Value, index []int) {
field, err := field.FieldByIndexErr(index)
if err == nil && field.IsValid() {
field.Set(reflect.Zero(field.Type())) // NOTE: Go1.18 has no SetZero
}
}
// nillableValueSetNilOnZero sets value as `nil` when its inner value is zero.
// Only applies to `Pointer`, `Interface`, `Slice` and `Map` types.
func nillableValueSetNilOnZero(val reflect.Value) {
innerVal := val
for {
switch innerVal.Kind() { //nolint:exhaustive
case reflect.Pointer, reflect.Interface:
innerVal = innerVal.Elem()
if !innerVal.IsValid() || innerVal.IsZero() {
val.Set(reflect.Zero(val.Type())) // NOTE: Go1.18 has no SetZero
return
}
case reflect.Slice, reflect.Map:
if innerVal.Len() == 0 {
val.Set(reflect.Zero(val.Type())) // NOTE: Go1.18 has no SetZero
}
return // always return as we can't go deeper with a slice or map
default:
return
}
}
}