github.com/litesolutions/justifay-api@v1.0.0-2.0.20220707114139-46f28a909481/internal/pkg/structs/merge.go (about)

     1  package structs
     2  
     3  import (
     4  	"reflect"
     5  )
     6  
     7  // Merge receives two structs, and merges them excluding fields with tag name: `structs`, value "-"
     8  func Merge(dst, src interface{}) {
     9  	s := reflect.ValueOf(src)
    10  	d := reflect.ValueOf(dst)
    11  	if s.Kind() != reflect.Ptr || d.Kind() != reflect.Ptr {
    12  		return
    13  	}
    14  	for i := 0; i < s.Elem().NumField(); i++ {
    15  		v := s.Elem().Field(i)
    16  		fieldName := s.Elem().Type().Field(i).Name
    17  		skip := s.Elem().Type().Field(i).Tag.Get("structs")
    18  		if skip == "-" {
    19  			continue
    20  		}
    21  		if v.Kind() > reflect.Float64 &&
    22  			v.Kind() != reflect.String &&
    23  			v.Kind() != reflect.Struct &&
    24  			v.Kind() != reflect.Ptr &&
    25  			v.Kind() != reflect.Slice {
    26  			continue
    27  		}
    28  		if v.Kind() == reflect.Ptr {
    29  			// Field is pointer check if it's nil or set
    30  			if !v.IsNil() {
    31  				// Field is set assign it to dest
    32  
    33  				if d.Elem().FieldByName(fieldName).Kind() == reflect.Ptr {
    34  					d.Elem().FieldByName(fieldName).Set(v)
    35  					continue
    36  				}
    37  				f := d.Elem().FieldByName(fieldName)
    38  				if f.IsValid() {
    39  					f.Set(v.Elem())
    40  				}
    41  			}
    42  			continue
    43  		}
    44  		d.Elem().FieldByName(fieldName).Set(v)
    45  	}
    46  }