Пример #1
0
/**
 *	创建结构体递归遍历子字段操作
 *
 *	@param structV			递归操作字段
 *	@param joinFieldName	字段连接名
 *	@param arraySizeMap		解析后的集合数量设值map
 */
func parampackNewStructFindFiled(structV reflect.Value, joinFieldName string, arraySizeMap map[string]int) {
	structV = reflect.Indirect(structV)
	if reflect.Struct != structV.Kind() {
		return
	}

	//	遍历结构字段寻找需要初始化的slice
	filedCount := structV.NumField()
	for i := 0; i < filedCount; i++ {
		childField := structV.Field(i)
		childFieldType := childField.Type()
		childFieldName := structV.Type().Field(i).Name

		if !childField.CanSet() {
			continue
		}

		if 0 != len(joinFieldName) && '.' != joinFieldName[len(joinFieldName)-1] {
			joinFieldName += "."
		}

		if reflect.Ptr == childFieldType.Kind() && childField.IsNil() {
			//	初始化子结构指针的操作
			childField.Set(reflect.New(childField.Type().Elem()))
		}

		switch reflect.Indirect(childField).Kind() {
		case reflect.Struct:
			if !parampackFilterParamPackStructType(childField.Type()) {
				parampackNewStructFindFiled(childField, joinFieldName+childFieldName, arraySizeMap)
			}
		case reflect.Slice:

			tempJoinName := joinFieldName + childFieldName

			if sliceSize, ok := arraySizeMap[strings.ToLower(tempJoinName)]; ok {

				valueElem := reflect.Indirect(childField)
				valueElem.Set(reflect.MakeSlice(valueElem.Type(), sliceSize, sliceSize))

				//	继续执行集合子元素的遍历
				if !parampackFilterParamPackStructType(valueElem.Type()) {
					for j := 0; j < sliceSize; j++ {
						childIndex := valueElem.Index(j)

						if reflect.Ptr == childIndex.Kind() && childIndex.IsNil() {
							//	初始化子元素指针的操作
							childIndex.Set(reflect.New(childIndex.Type().Elem()))
						}

						//	当前由于是数组类型,所以传递连接名的时候加上"[index]"下标往下进行操作
						tempJoinName = joinFieldName + childFieldName + "[" + strconv.Itoa(j) + "]"

						parampackNewStructFindFiled(childIndex, tempJoinName, arraySizeMap)
					}
				}
			}
		}
	}
}
Пример #2
0
/**
 *	根据field的字段名称设置struct字段属性值
 *	字段名称可为"type.tag.TagName", 以"."作为子字段的名称分割
 *
 *	@param sutValue		被设值的结构反射类型
 *	@param fieldName	字段名(type.tag.TagName) or (tagnName)
 *	@param value		设值值
 */
func parampackSetStructFieldValue(sutValue reflect.Value, fieldName string, value interface{}) {
	fieldName = strings.TrimSpace(fieldName)
	sutValueElem := reflect.Indirect(sutValue)

	if len(fieldName) == 0 {
		return
	}

	//	由于考虑到key的值可能为(type.tag.TagName),嵌套的赋值,所以需要进行"."的分割,每次获取slice的第一项
	fieldsName := strings.Split(fieldName, ".")
	childFieldName := strings.Title(fieldsName[0])

	if sutValueElem.Kind() == reflect.Slice {
		//	集合字段的设值操作

		strIndex := _arrayTagRex.FindString(childFieldName)
		if 0 >= len(strIndex) {
			//	判断如果是数组类型,但是设值的字段名称不是数组的标识则跳过(数组标识Users[0])
			//	由于有可能是需要直接设置数组参数,但是字段名称中(childFieldName = "Files")中未包含"[\d]"的标识
			//	所以尝试直接设值
			parampackSetParamValue(sutValueElem, fieldName, value)
			return
		}

		intIndex, e := strconv.Atoi(strIndex[1 : len(strIndex)-1])
		if nil == e && intIndex < sutValueElem.Len() {
			fieldValue := sutValueElem.Index(intIndex)

			parampackSetFieldValue(fieldValue, fieldName, fieldsName, value)
		}

	} else {

		//	判断是否为数组标识,如果是的话就删除,例如:Users[0] 删除[0] = Users
		//	这样便于FieldByName查找到相应的字段信息
		reIndex := _arrayTagRex.FindStringIndex(childFieldName)
		if 0 < len(reIndex) {
			childFieldName = childFieldName[:reIndex[0]]
		}

		//	查找字段
		fieldValue := sutValueElem.FieldByName(childFieldName)

		parampackSetFieldValue(fieldValue, fieldName, fieldsName, value)
	}
}