我正在try 学习Golang定制验证,但遇到了很多麻烦.以下是我一直在try 的代码:

package main
import (
        "reflect"
        "github.com/go-playground/validator/v10"
        "fmt"
)
type TeamMember struct {
        Country string
        Age int
        DropShip bool `validate:"is_eligible"`
}
func CustomValidation(fl validator.FieldLevel) bool {
  /*
    if(DropShip == true) {
       httpresponse = curl https://3rd-party-api.com/?country=<Country>&age=<Age>
       return httpresponse.code == 200
    }
    return false
  */

  b := fl.Parent()
  fmt.Println(reflect.TypeOf(b))
  fmt.Println(reflect.ValueOf(b))
  c := reflect.ValueOf(b).Interface()
  fmt.Println(c.(TeamMember))
  fmt.Println("============")
  return true
}


func main() {
  var validate *validator.Validate
  validate = validator.New(validator.WithRequiredStructEnabled())
  _ = validate.RegisterValidation("is_eligible", CustomValidation)
  teammember := TeamMember{"Canada", 34, true}

  validate.Struct(teammember)
}

您可以在代码注释中看到我正在try 的验证逻辑……如果DropShip字段为真,那么我需要将CountryAge提交给另一个API,以查看该团队成员是否符合条件.

问题是,我很难使用reflect库来访问TeamMember struct 中的CountryAge字段.fmt.Println(c.(TeamMember))行使我的程序崩溃.

有人能给我一个如何访问其他团队成员字段的例子吗?或者,我的验证方法违反了golang 语中惯用的验证方式?

推荐答案

在这种情况下,最好使用定制的 struct 级别验证:

package main

import (
    "fmt"

    "github.com/go-playground/validator/v10"
)

type TeamMember struct {
    Country  string
    Age      int
    DropShip bool
}

func TeamMemberStructLevelValidation(sl validator.StructLevel) {
    teamMember := sl.Current().Interface().(TeamMember)

    if teamMember.DropShip {
        // submit the Country and Age to another API to see if this team member is eligible.
        if teamMember.Country == "Canada" && teamMember.Age == 34 {
            sl.ReportError(teamMember.Country, "country", "Country", "is_eligible", "")
            sl.ReportError(teamMember.Age, "age", "Age", "is_eligible", "")
        }
    }
}

func main() {
    validate := validator.New(validator.WithRequiredStructEnabled())
    validate.RegisterStructValidation(TeamMemberStructLevelValidation, TeamMember{})

    teamMember := TeamMember{"Canada", 34, true}
    err := validate.Struct(teamMember)

    fmt.Printf("%+v\n", err)
    // Output:
    //   Key: 'TeamMember.country' Error:Field validation for 'country' failed on the 'is_eligible' tag
    //   Key: 'TeamMember.age' Error:Field validation for 'age' failed on the 'is_eligible' tag
}

另请参阅此包提供的示例:https://github.com/go-playground/validator/blob/v10.15.3/_examples/struct-level/main.go.

Go相关问答推荐

如何在jsonrpc服务器的服务器端捕获错误?

错误.如果它包含切片,则返回FALSE

使用Go使用Gorm使用外键对数据进行排序

调用库和直接操作效率有区别吗?

在 Go 中将元数据从一个 JPEG 复制到另一个

是否可以将 http.ServeHttp 包装在 go 中以使用 alexedwards/scs/v2 添加会话

Golang 创建一个带有处理程序的模拟数据库并使用接口调用数据库

在 Go 模板中对照片使用随机 Int

如何在 Docker 容器中使用私有存储库进行身份验证

如何将具有嵌入式 struct 的 struct 展平为 json

如何使用特定的 Go 版本运行 govulncheck?

为什么 0 big.Int 的 .Bytes() 值是空切片?

将未知长度切片的值分配给Go中的 struct ?

在 connect-go 拦截器中修改响应体

go mod tidy 错误消息:但是 go 1.16 会 Select

无法识别同步错误.使用一次

将基本 HTTP AUth 用户/密码凭据存储在 GO 中,无需外部包

如何断言类型是指向golang中接口的指针

关于GO的几个问题

如何动态解析 Go Fiber 中的请求正文?