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
}