func (a tagKVs) Less(i, j int) bool {
	return a[i].pos < a[j].pos
}
Less reports whether the element with
index i should sort before the element with index j.
package binding
import (
	"net/textproto"
	"reflect"
	"sort"
	"strings"
	"github.com/henrylee2cn/goutil"
)
const (
	tagRequired         = "required"
	tagRequired2        = "req"
	defaultTagPath      = "path"
	defaultTagQuery     = "query"
	defaultTagHeader    = "header"
	defaultTagCookie    = "cookie"
	defaultTagRawbody   = "raw_body"
	defaultTagForm      = "form"
	defaultTagValidator = "vd"
	tagProtobuf         = "protobuf"
	tagJSON             = "json"
	tagDefault          = "default"
)
type Config struct {
	LooseZeroMode bool
	PathParam string
	Query string
	Header string
	Cookie string
	RawBody string
	FormBody string
	Validator string
	protobufBody string
	jsonBody string
	defaultVal string
	list []string
}
func (t *Config) init() {
	t.list = []string{
		goutil.InitAndGetString(&t.PathParam, defaultTagPath),
		goutil.InitAndGetString(&t.Query, defaultTagQuery),
		goutil.InitAndGetString(&t.Header, defaultTagHeader),
		goutil.InitAndGetString(&t.Cookie, defaultTagCookie),
		goutil.InitAndGetString(&t.RawBody, defaultTagRawbody),
		goutil.InitAndGetString(&t.FormBody, defaultTagForm),
		goutil.InitAndGetString(&t.Validator, defaultTagValidator),
		goutil.InitAndGetString(&t.protobufBody, tagProtobuf),
		goutil.InitAndGetString(&t.jsonBody, tagJSON),
		goutil.InitAndGetString(&t.defaultVal, tagDefault),
	}
}
func (t *Config) parse(field reflect.StructField) tagKVs {
	tag := field.Tag
	fieldName := field.Name
	kvs := make(tagKVs, 0, len(t.list))
	s := string(tag)
	for _, name := range t.list {
		value, ok := tag.Lookup(name)
		if !ok {
			continue
		}
		if name != t.defaultVal && value != "-" {
			value = strings.Replace(strings.TrimSpace(value), " ", "", -1)
			value = strings.Replace(value, "\t", "", -1)
			if name == t.RawBody {
				info := newTagInfo(value, false)
				if info.required || info.paramName == tagRequired {
					value = "," + tagRequired
				}
			} else if value == "" {
				value = fieldName
			} else if value == ","+tagRequired {
				value = fieldName + value
			}
		}
		kvs = append(kvs, &tagKV{name: name, value: value, pos: strings.Index(s, name)})
	}
	sort.Sort(kvs)
	return kvs
}
type tagKV struct {
	name  string
	value string
	pos   int
}
type tagInfo struct {
	paramIn   in
	paramName string
	required  bool
	namePath  string
	requiredError, typeError, cannotError, contentTypeError error
}
func (t *tagKV) toInfo(isHeader bool) *tagInfo {
	return newTagInfo(t.value, isHeader)
}
func newTagInfo(value string, isHeader bool) *tagInfo {
	info := new(tagInfo)
	for i, v := range strings.Split(value, ",") {
		v = strings.TrimSpace(v)
		if i == 0 {
			info.paramName = v
		} else {
			if v == tagRequired || v == tagRequired2 {
				info.required = true
			}
		}
	}
	if isHeader {
		info.paramName = textproto.CanonicalMIMEHeaderKey(info.paramName)
	}
	return info
}
type tagKVs []*tagKV
func (a tagKVs) Len() int {
	return len(a)
}