func fieldUnfolders()

in gotype/unfold_struct.go [66:123]


func fieldUnfolders(ctx *unfoldCtx, t reflect.Type) (map[string]fieldUnfolder, error) {
	count := t.NumField()
	fields := map[string]fieldUnfolder{}

	for i := 0; i < count; i++ {
		st := t.Field(i)

		name := st.Name
		rune, _ := utf8.DecodeRuneInString(name)
		if !unicode.IsUpper(rune) {
			continue
		}

		tagName, tagOpts := parseTags(st.Tag.Get(ctx.opts.tag))
		if tagOpts.omit {
			continue
		}

		if tagOpts.squash {
			if st.Type.Kind() != reflect.Struct {
				return nil, errSquashNeedObject
			}

			sub, err := fieldUnfolders(ctx, st.Type)
			if err != nil {
				return nil, err
			}

			for name, fu := range sub {
				fu.offset += st.Offset
				if _, exists := fields[name]; exists {
					return nil, fmt.Errorf("duplicate field name %v", name)
				}

				fields[name] = fu
			}
		} else {
			if tagName != "" {
				name = tagName
			} else {
				name = strings.ToLower(name)
			}

			if _, exists := fields[name]; exists {
				return nil, fmt.Errorf("duplicate field name %v", name)
			}

			fu, err := makeFieldUnfolder(ctx, st)
			if err != nil {
				return nil, err
			}

			fields[name] = fu
		}
	}

	return fields, nil
}