Validation go中验证http请求的惯用方法

Validation go中验证http请求的惯用方法,validation,http,go,Validation,Http,Go,我需要验证我的http请求是否有两个参数,Start和End。目前,我设置了一个默认值,该值不应显示为任何一个参数,并与其他无效值一起检查。然而,这感觉像是一个黑客。正确的方法应该是什么 这是我的密码: type Request struct { Start int `json: "start"` End int `json: "end"` } func HandlePost(w http.ResponseWriter, r *http.Request) { body

我需要验证我的http请求是否有两个参数,Start和End。目前,我设置了一个默认值,该值不应显示为任何一个参数,并与其他无效值一起检查。然而,这感觉像是一个黑客。正确的方法应该是什么

这是我的密码:

type Request struct {
    Start int `json: "start"`
    End int `json: "end"`
}


func HandlePost(w http.ResponseWriter, r *http.Request) {
    body , _ := ioutil.ReadAll(r.Body)
    reqData := Request{Start: -1, End: -1} // < whats the correct way to do this
    json.Unmarshal(body, &reqData)  

    if reqData.Start < 0 && reqData.End < 0 {
        w.WriteHeader(http.StatusBadRequest)
        return
    }
    // rest of the logic
}
类型请求结构{
Start int`json:“Start”`
End int`json:“End”`
}
func HandlePost(w http.ResponseWriter,r*http.Request){
body,Util:=ioutil.ReadAll(r.body)
reqData:=请求{开始:-1,结束:-1}/<正确的方法是什么
Unmarshal(body和reqData)
如果reqData.Start<0&&reqData.End<0{
w、 WriteHeader(http.StatusBadRequest)
返回
}
//其余的逻辑
}
您可以使用getInt。 如果json缺少所需的键,则会出现错误

我建议使用基准测试,而不是由代码美或任何其他预感决定,您可以使用这些预感作为验证请求的基本方法。但如果您想要更复杂的东西,您需要编写自己的自定义验证器函数。e、 g

type Request struct {
    Start int `json: "start"`
    End int `json: "end"`
}

func (a *Request) validate() url.Values {
    err := url.Values{}

    // Write your own validation rules
    if a.Start < 0 {
        err.Add("Start", "Start cannot be less than 0");
    }

    return err;
}

func handler(w http.ResponseWriter, r *http.Request) {
    requestBody := &Request{}

    defer r.Body.Close()
    if err := json.NewDecoder(r.Body).Decode(requestBody); err != nil {
        panic(err)
    }

    if errors := requestBody.validate(); len(errors) > 0 {
        err := map[string]interface{}{"validationError": errors}
        w.Header().Set("Content-type", "application/json")
        w.WriteHeader(http.StatusBadRequest)
        json.NewEncoder(w).Encode(err)
    }

    fmt.Fprint(w, "success request scenario!")
}
类型请求结构{
Start int`json:“Start”`
End int`json:“End”`
}
func(a*请求)validate()url.Values{
错误:=url.Values{}
//编写自己的验证规则
如果a.开始<0{
错误添加(“开始”,“开始不能小于0”);
}
返回错误;
}
func处理程序(w http.ResponseWriter,r*http.Request){
requestBody:=&请求{}
延迟r.Body.Close()
如果err:=json.NewDecoder(r.Body).Decode(requestBody);err!=nil{
恐慌(错误)
}
如果错误:=requestBody.validate();len(错误)>0{
err:=map[string]接口{}{“validationError”:errors}
w、 Header().Set(“内容类型”、“应用程序/json”)
w、 WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(err)
}
Fprint(w,“成功请求场景!”)
}

下面是使用结构标记和指针验证结构的另一种方法。请注意,如果0是要传递的有效对象,则此解决方案将不起作用。 omitempty认为0值为空。如果您想让它工作,将考虑0是有效的,请删除指针并修改IsValid方法

package main

import (
    "encoding/json"
    "fmt"
)

type Request struct {
    Start *int `json: "start,omitempty"`
    End   *int `json: "end,omitempty"`
}

func (r Request) IsValid() (bool, error) {
    if r.Start == nil {
        return false, fmt.Errorf("start is missing")
    }

    if r.End == nil {
        return false, fmt.Errorf("end is missing")
    }

    return true, nil
}

var (
    invalidStartb = `{"end": 1}`
    invalidEndb   = `{"start": 1}`
    valid         = `{"start": 1, "end": 1}`
)

func main() {
    var r Request

    _ = json.Unmarshal([]byte(invalidStartb), &r)
    fmt.Println(r.IsValid())

    r = Request{}
    _ = json.Unmarshal([]byte(invalidEndb), &r)
    fmt.Println(r.IsValid())

    r = Request{}
    _ = json.Unmarshal([]byte(valid), &r)
    fmt.Println(r.IsValid())

}

这里的可运行版本

通常你会使用指针:如果请求中没有传递任何值,那么字段将保持为
nil
。可能重复感谢,@mkopriva和zaky得到了我想要的答案。其他答案使用的外部库可能不那么惯用。你们中的任何一个能回答吗?我将把它标记为已接受的答案?请注意,这个问题实际上与HTTP无关。正如@mkopriva提到的,惯用的方法是使用指针,而不是使用库。通过使用指针,当未指定时,该值将为
nil
,而不是设置为0。当您希望在未提供值的情况下设置默认值时,指针可能是惯用的方法。当您想要验证时,可能是错误的方式。假设您有一个很大的属性列表,通过使用指针,您可以解组整个结构,只是为了发现它无效。假设您有几个字段需要验证,在这种情况下,您可以先检查可能丢失的最有可能的字段,然后快速返回。糟糕的是,我一开始就误解了这个问题,使用验证器库更好。很抱歉:p@Ullaakut然后再把你的票否决:)当然,如果是你的话。非常感谢。