Golang中如何对Post请求的Form Data进行验证?
问题描述
我在Golang的Echo框架中通过Post请求获取Form Data,希望在将数据传入数据库查询前进行验证。我了解可通过绑定方式对JSON类型数据使用validator库验证,现有如下含validate标签的Game结构体:
type Game struct { Id string `json:"Id"` Name string `json:"Name" validate:"required"` Rating float32 `json:"Rating"` TimesPlayed int `json:"TimesPlayed" validate:"required, number"` ImagePath string `json:"ImagePath" validate:"required, file"` Description string `json:"Description"` Developer string `json:"Developer" validate:"required, min=5, max=20"` CreationDate time.Time `json:"CreationDate"` Version string `json:"Version"` Tags []string `json:"Tags"` Downloads int64 `json:"Downloads" validate:"number"` // firestore doesn't support uint64 DownloadLink string `json:"DownloadLink" validate:"required, uri"` }
目前我通过c.FormValue直接赋值未做验证,代码如下:
func newGameHandler(c echo.Context) error { // create new game model // TODO need a security layer in between the form and our new game struct newGame := models.Game{ Name: c.FormValue(NAME), Developer: c.FormValue(DEVELOPER), CreationDate: time.Now(), Version: c.FormValue(VERSION), } // Add new game to database _db, getDbErr := db.NewDatabaseFromEnv() _, err := _db.AddGame(newGame) // error handling if getDbErr != nil { return c.JSON(http.StatusInternalServerError, "Database connection error") } if err != nil { return c.JSON(http.StatusInternalServerError, "Database add game error") } // TODO return successful game add return c.JSON(http.StatusOK, "New game handler") }
请问如何利用validator库对这些Form Data进行验证?
解决方案
1. 安装validator库
先确保安装了go-playground/validator:
go get github.com/go-playground/validator/v10
2. 给结构体补充form标签
Echo的表单绑定需要字段带有form标签,和前端表单字段名对应。修改Game结构体:
type Game struct { Id string `json:"Id" form:"Id"` Name string `json:"Name" form:"Name" validate:"required"` Rating float32 `json:"Rating" form:"Rating"` TimesPlayed int `json:"TimesPlayed" form:"TimesPlayed" validate:"required, number"` ImagePath string `json:"ImagePath" form:"ImagePath" validate:"required, file"` Description string `json:"Description" form:"Description"` Developer string `json:"Developer" form:"Developer" validate:"required, min=5, max=20"` CreationDate time.Time `json:"CreationDate" form:"CreationDate"` Version string `json:"Version" form:"Version"` Tags []string `json:"Tags" form:"Tags"` Downloads int64 `json:"Downloads" form:"Downloads" validate:"number"` DownloadLink string `json:"DownloadLink" form:"DownloadLink" validate:"required, uri"` }
若表单字段名和结构体字段名完全一致,
form标签可省略,但显式声明更清晰。
3. 在Handler中绑定并验证表单数据
替换手动赋值逻辑,用Echo的c.Bind()自动绑定表单数据,再执行验证:
import ( "net/http" "time" "os" "github.com/go-playground/validator/v10" "github.com/labstack/echo/v4" ) // 全局初始化验证器实例,避免重复创建 var validate *validator.Validate func init() { validate = validator.New() // 若需要自定义"file"验证规则,注册自定义函数(示例) err := validate.RegisterValidation("file", func(fl validator.FieldLevel) bool { filePath := fl.Field().String() // 示例逻辑:检查文件是否存在 _, err := os.Stat(filePath) return err == nil }) if err != nil { panic("注册自定义验证规则失败:" + err.Error()) } } func newGameHandler(c echo.Context) error { var newGame models.Game // 绑定表单数据到结构体 if err := c.Bind(&newGame); err != nil { return c.JSON(http.StatusBadRequest, "表单数据绑定失败:"+err.Error()) } // 设置默认值 newGame.CreationDate = time.Now() // 执行验证 if err := validate.Struct(newGame); err != nil { // 整理验证错误信息 var errMsg []string for _, e := range err.(validator.ValidationErrors) { errMsg = append(errMsg, "字段"+e.Field()+"验证失败:违反"+e.Tag()+"规则") } return c.JSON(http.StatusBadRequest, map[string]interface{}{ "errors": errMsg, }) } // 数据库操作 _db, getDbErr := db.NewDatabaseFromEnv() if getDbErr != nil { return c.JSON(http.StatusInternalServerError, "数据库连接错误") } _, err := _db.AddGame(newGame) if err != nil { return c.JSON(http.StatusInternalServerError, "添加游戏到数据库失败") } return c.JSON(http.StatusOK, map[string]string{ "message": "游戏添加成功", }) }
关键说明
c.Bind()会自动处理表单数据的类型转换(比如字符串转int、float32),避免手动转换的错误。- 验证失败返回
400 Bad Request,并返回具体错误字段和规则,方便前端定位问题。 - 全局初始化验证器,提升请求处理性能。
内容的提问来源于stack exchange,提问作者Pravin Poudel
相关产品推荐
相关产品推荐

