bytedance / go-tagexpr

An interesting go struct tag expression syntax for field validation, etc.
Apache License 2.0
1.66k stars 142 forks source link

bindStruct中在for循环里面进行header取数,会有内存和性能问题,可以统一放到外部处理 #59

Open KunWang2 opened 1 year ago

KunWang2 commented 1 year ago

func (b *Binding) bindStruct(structPointer interface{}, structValue reflect.Value, req Request, pathParams PathParams) (hasVd bool, err error) { recv, err := b.getOrPrepareReceiver(structValue) if err != nil { return }

expr, err := b.vd.VM().Run(structValue)
if err != nil {
    return
}

bodyCodec, bodyBytes, err := recv.getBodyInfo(req)
if len(bodyBytes) > 0 {
    err = b.prebindBody(structPointer, structValue, bodyCodec, bodyBytes)
}
if err != nil {
    return
}
bodyString := ameda.UnsafeBytesToString(bodyBytes)
postForm, err := req.GetPostForm()
if err != nil {
    return
}
var fileHeaders map[string][]*multipart.FileHeader
if _req, ok := req.(requestWithFileHeader); ok {
    fileHeaders, err = _req.GetFileHeaders()
    if err != nil {
        return
    }
}
queryValues := recv.getQuery(req)
cookies := recv.getCookies(req)
headers := req.GetHeader()

for _, param := range recv.params {
    for i, info := range param.tagInfos {
        var found bool
        switch info.paramIn {
        case raw_body:
            err = param.bindRawBody(info, expr, bodyBytes)
            found = err == nil
        case path:
            found, err = param.bindPath(info, expr, pathParams)
        case query:
            found, err = param.bindQuery(info, expr, queryValues)
        case cookie:
            found, err = param.bindCookie(info, expr, cookies)
        case header:
            found, err = param.bindHeader(info, expr, headers)
        case form, json, protobuf:
            if info.paramIn == in(bodyCodec) {
                found, err = param.bindOrRequireBody(info, expr, bodyCodec, bodyString, postForm, fileHeaders,
                    recv.hasDefaultVal)
            } else if info.required {
                found = false
                err = info.requiredError
            }
        case default_val:
            found, err = param.bindDefaultVal(expr, param.defaultVal)
        }
        if found && err == nil {
            break
        }
        if (found || i == len(param.tagInfos)-1) && err != nil {
            return recv.hasVd, err
        }
    }
}
return recv.hasVd, nil

}