英文:
Validate enum in Golang using Gin framework
问题
我尝试使用Gin框架在Golang中验证枚举是否有效。
我找到了这个解决方案:
但这种方法的缺点是硬编码的值,每次枚举值更改时都需要手动更改。
有没有一种方法可以通过枚举的名称作为字符串来获取枚举,而无需创建和注册类型的映射?
期望的结果:
package main
import "github.com/go-playground/validator"
type Status int
const (
Single Status = iota
Married
Other
)
type User struct {
Status Status `json:"status" binding:"Enum=Status"`
}
func Enum(fl validator.FieldLevel) bool {
enumType := fl.Param() // Status
// 通过 `enumType` 获取 `Status` 并进行验证...
return true
}
func main() {}
英文:
I try to validate if enum is valid in Golang using Gin framework.
I came across this solution:
But disadvantage of this approach is hardcoded value which we have to change manually every time enum value has changed.
Is there any way to get enum by its name as string without creating and register the map with types?
Desired result:
package main
import "github.com/go-playground/validator"
type Status int
const (
Single Status = iota
Married
Other
)
type User struct {
Status Status `json:"status" binding:"Enum=Status"`
}
func Enum(fl validator.FieldLevel) bool {
enumType := fl.Param() // Status
// get `Status` by `enumType` and validate it...
return true
}
func main() {}
答案1
得分: 1
以下是翻译好的内容:
解决方案之一可能是:
package main
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/validator/v10"
)
type Enum interface {
IsValid() bool
}
type Status int
const (
Single Status = iota + 1 // 添加 +1,否则验证对于0将不起作用
Married
Other
)
func (s Status) IsValid() bool {
switch s {
case Single, Married, Other:
return true
}
return false
}
type Input struct {
RelationshipStatus Status `json:"relationship_status" binding:"required,enum"`
}
func UpdateRelationshipStatus(context *gin.Context) {
input := Input{}
err := context.ShouldBindJSON(&input)
if err != nil {
context.JSON(http.StatusBadRequest, gin.H{"message": "枚举无效"})
return
}
context.JSON(http.StatusOK, gin.H{"message": "正确的枚举"})
}
func ValidateEnum(fl validator.FieldLevel) bool {
value := fl.Field().Interface().(Enum)
return value.IsValid()
}
func main() {
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
v.RegisterValidation("enum", ValidateEnum)
}
router := gin.Default()
router.POST("", UpdateRelationshipStatus)
router.Run(":3000")
}
输出:
curl \
--request POST \
--data '{"relationship_status": 0}' \
http://localhost:3000/
# {"message":"枚举无效"}
curl \
--request POST \
--data '{"relationship_status": 1}' \
http://localhost:3000/
# {"message":"正确的枚举"}
curl \
--request POST \
--data '{"relationship_status": 2}' \
http://localhost:3000/
# {"message":"正确的枚举"}
curl \
--request POST \
--data '{"relationship_status": 3}' \
http://localhost:3000/
# {"message":"正确的枚举"}
curl \
--request POST \
--data '{"relationship_status": 4}' \
http://localhost:3000/
# {"message":"枚举无效"}
英文:
One of the approach to this solution could be:
package main
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/validator/v10"
)
type Enum interface {
IsValid() bool
}
type Status int
const (
Single Status = iota + 1 // add + 1 otherwise validation won't work for 0
Married
Other
)
func (s Status) IsValid() bool {
switch s {
case Single, Married, Other:
return true
}
return false
}
type Input struct {
RelationshipStatus Status `json:"relationship_status" binding:"required,enum"`
}
func UpdateRelationshipStatus(context *gin.Context) {
input := Input{}
err := context.ShouldBindJSON(&input)
if err != nil {
context.JSON(http.StatusBadRequest, gin.H{"message": "enum is not valid"})
return
}
context.JSON(http.StatusOK, gin.H{"message": "correct enum"})
}
func ValidateEnum(fl validator.FieldLevel) bool {
value := fl.Field().Interface().(Enum)
return value.IsValid()
}
func main() {
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
v.RegisterValidation("enum", ValidateEnum)
}
router := gin.Default()
router.POST("", UpdateRelationshipStatus)
router.Run(":3000")
}
Output:
curl \
--request POST \
--data '{"relationship_status": 0}' \
http://localhost:3000/
# {"message":"enum is not valid"}
curl \
--request POST \
--data '{"relationship_status": 1}' \
http://localhost:3000/
# {"message":"correct enum"}
curl \
--request POST \
--data '{"relationship_status": 2}' \
http://localhost:3000/
# {"message":"correct enum"}
curl \
--request POST \
--data '{"relationship_status": 3}' \
http://localhost:3000/
# {"message":"correct enum"}
curl \
--request POST \
--data '{"relationship_status": 4}' \
http://localhost:3000/
# {"message":"enum is not valid"}
答案2
得分: 1
同意mikolaj的答案。但为了避免这种方法带来的缺点,你可以尝试利用类似https://github.com/nishanths/exhaustive的工具,它可以在CICD系统中检查和报告错误,以防止你忘记在switch语句中处理新的const值。
英文:
Agree with mikolaj's answer. But to avoid the disadvantage which comes with this approach, you can try to leverage something like https://github.com/nishanths/exhaustive which checks and errors in CICD systems if you forget to handle the new const value in switch cases.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论