| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 | package coppier/* * source https://github.com/jinzhu/copier.git */import (	"database/sql"	"errors"	"reflect")// Copy copy thingsfunc Copy(toValue interface{}, fromValue interface{}) (err error) {	var (		isSlice bool		amount  = 1		from    = indirect(reflect.ValueOf(fromValue))		to      = indirect(reflect.ValueOf(toValue))	)	if !to.CanAddr() {		return errors.New("copy to value is unaddressable")	}	// Return is from value is invalid	if !from.IsValid() {		return	}	fromType := indirectType(from.Type())	toType := indirectType(to.Type())	// Just set it if possible to assign	// And need to do copy anyway if the type is struct	if fromType.Kind() != reflect.Struct && from.Type().AssignableTo(to.Type()) {		to.Set(from)		return	}	if fromType.Kind() != reflect.Struct || toType.Kind() != reflect.Struct {		return	}	if to.Kind() == reflect.Slice {		isSlice = true		if from.Kind() == reflect.Slice {			amount = from.Len()		}	}	for i := 0; i < amount; i++ {		var dest, source reflect.Value		if isSlice {			// source			if from.Kind() == reflect.Slice {				source = indirect(from.Index(i))			} else {				source = indirect(from)			}			// dest			dest = indirect(reflect.New(toType).Elem())		} else {			source = indirect(from)			dest = indirect(to)		}		// check source		if source.IsValid() {			fromTypeFields := deepFields(fromType)			//fmt.Printf("%#v", fromTypeFields)			// Copy from field to field or method			for _, field := range fromTypeFields {				name := field.Name				if fromField := source.FieldByName(name); fromField.IsValid() {					// has field					if toField := dest.FieldByName(name); toField.IsValid() {						if toField.CanSet() {							if !set(toField, fromField) {								if err := Copy(toField.Addr().Interface(), fromField.Interface()); err != nil {									return err								}							}						}					} else {						// try to set to method						var toMethod reflect.Value						if dest.CanAddr() {							toMethod = dest.Addr().MethodByName(name)						} else {							toMethod = dest.MethodByName(name)						}						if toMethod.IsValid() && toMethod.Type().NumIn() == 1 && fromField.Type().AssignableTo(toMethod.Type().In(0)) {							toMethod.Call([]reflect.Value{fromField})						}					}				}			}			// Copy from method to field			for _, field := range deepFields(toType) {				name := field.Name				var fromMethod reflect.Value				if source.CanAddr() {					fromMethod = source.Addr().MethodByName(name)				} else {					fromMethod = source.MethodByName(name)				}				if fromMethod.IsValid() && fromMethod.Type().NumIn() == 0 && fromMethod.Type().NumOut() == 1 {					if toField := dest.FieldByName(name); toField.IsValid() && toField.CanSet() {						values := fromMethod.Call([]reflect.Value{})						if len(values) >= 1 {							set(toField, values[0])						}					}				}			}		}		if isSlice {			if dest.Addr().Type().AssignableTo(to.Type().Elem()) {				to.Set(reflect.Append(to, dest.Addr()))			} else if dest.Type().AssignableTo(to.Type().Elem()) {				to.Set(reflect.Append(to, dest))			}		}	}	return}func deepFields(reflectType reflect.Type) []reflect.StructField {	var fields []reflect.StructField	if reflectType = indirectType(reflectType); reflectType.Kind() == reflect.Struct {		for i := 0; i < reflectType.NumField(); i++ {			v := reflectType.Field(i)			if v.Anonymous {				fields = append(fields, deepFields(v.Type)...)			} else {				fields = append(fields, v)			}		}	}	return fields}func indirect(reflectValue reflect.Value) reflect.Value {	for reflectValue.Kind() == reflect.Ptr {		reflectValue = reflectValue.Elem()	}	return reflectValue}func indirectType(reflectType reflect.Type) reflect.Type {	for reflectType.Kind() == reflect.Ptr || reflectType.Kind() == reflect.Slice {		reflectType = reflectType.Elem()	}	return reflectType}func set(to, from reflect.Value) bool {	if from.IsValid() {		if to.Kind() == reflect.Ptr {			//set `to` to nil if from is nil			if from.Kind() == reflect.Ptr && from.IsNil() {				to.Set(reflect.Zero(to.Type()))				return true			} else if to.IsNil() {				to.Set(reflect.New(to.Type().Elem()))			}			to = to.Elem()		}		if from.Type().ConvertibleTo(to.Type()) {			to.Set(from.Convert(to.Type()))		} else if scanner, ok := to.Addr().Interface().(sql.Scanner); ok {			err := scanner.Scan(from.Interface())			if err != nil {				return false			}		} else if from.Kind() == reflect.Ptr {			return set(to, from.Elem())		} else {			return false		}	}	return true}
 |