Golang中类似Laravel的功能有哪些
Golang中类似Laravel的功能有哪些 在验证器(validator)中,当尝试验证一条记录并检查某个值是否存在于特定表中时,Golang 中与 Laravel 的 “exist” 功能等效的是什么?
2 回复
Golang中类似Laravel的功能有哪些 在验证器(validator)中,当尝试验证一条记录并检查某个值是否存在于特定表中时,Golang 中与 Laravel 的 “exist” 功能等效的是什么?
在Golang中实现类似Laravel的"exist"验证功能,可以使用go-playground/validator库配合自定义验证规则。以下是具体实现:
package main
import (
"context"
"database/sql"
"fmt"
"log"
"github.com/go-playground/validator/v10"
_ "github.com/lib/pq"
)
// 数据库连接
var db *sql.DB
// 自定义验证函数 - 检查用户ID是否存在
func validateUserIDExists(fl validator.FieldLevel) bool {
userID := fl.Field().Int()
query := "SELECT COUNT(*) FROM users WHERE id = $1"
var count int
err := db.QueryRowContext(context.Background(), query, userID).Scan(&count)
if err != nil {
return false
}
return count > 0
}
// 自定义验证函数 - 通用存在性检查
func validateExists(fl validator.FieldLevel) bool {
// 从参数获取表名和字段名
params := fl.Param()
// 格式: table,column
// 例如: "users,id" 或 "products,sku"
value := fl.Field().String()
query := fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE %s = $1", params)
var count int
err := db.QueryRowContext(context.Background(), query, value).Scan(&count)
if err != nil {
return false
}
return count > 0
}
type User struct {
ID int64 `validate:"required,userExists"`
Email string `validate:"required,email,exists=users,email"`
RoleID int64 `validate:"required,exists=roles,id"`
}
func main() {
// 初始化数据库连接
var err error
db, err = sql.Open("postgres", "host=localhost port=5432 user=postgres password=secret dbname=mydb sslmode=disable")
if err != nil {
log.Fatal(err)
}
defer db.Close()
// 创建验证器实例
validate := validator.New()
// 注册自定义验证函数
validate.RegisterValidation("userExists", validateUserIDExists)
validate.RegisterValidation("exists", validateExists)
// 测试验证
user := User{
ID: 100,
Email: "test@example.com",
RoleID: 1,
}
err = validate.Struct(user)
if err != nil {
if validationErrors, ok := err.(validator.ValidationErrors); ok {
for _, fieldError := range validationErrors {
fmt.Printf("字段 %s 验证失败: %s\n", fieldError.Field(), fieldError.Tag())
}
}
} else {
fmt.Println("验证通过")
}
}
更灵活的GORM集成方案:
package main
import (
"fmt"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"github.com/go-playground/validator/v10"
)
type User struct {
ID uint `validate:"required,existsInTable=users"`
Email string `validate:"required,email,existsInTable=users,email"`
}
var db *gorm.DB
// GORM存在性验证
func validateExistsInTable(fl validator.FieldLevel) bool {
tableName := fl.Param()
fieldName := "id" // 默认字段
// 如果指定了字段名,格式为: table,field
if len(fl.Param()) > 0 {
params := fl.Param()
// 解析参数获取表名和字段名
}
value := fl.Field().Interface()
var count int64
db.Table(tableName).Where(fieldName+" = ?", value).Count(&count)
return count > 0
}
func main() {
// 初始化GORM
dsn := "host=localhost user=postgres password=secret dbname=mydb port=5432 sslmode=disable"
db, _ = gorm.Open(postgres.Open(dsn), &gorm.Config{})
validate := validator.New()
validate.RegisterValidation("existsInTable", validateExistsInTable)
user := User{ID: 1, Email: "test@example.com"}
if err := validate.Struct(user); err != nil {
fmt.Printf("验证错误: %v\n", err)
}
}
使用ozzo-validation库的另一种实现:
package main
import (
"database/sql"
"fmt"
validation "github.com/go-ozzo/ozzo-validation/v4"
"github.com/go-ozzo/ozzo-validation/v4/is"
)
type Product struct {
SKU string `json:"sku"`
CategoryID int64 `json:"category_id"`
}
// 自定义存在性验证规则
func ExistsInTable(table, column string) validation.Rule {
return validation.By(func(value interface{}) error {
str := fmt.Sprintf("%v", value)
query := "SELECT COUNT(*) FROM " + table + " WHERE " + column + " = $1"
var count int
err := db.QueryRow(query, str).Scan(&count)
if err != nil {
return err
}
if count == 0 {
return fmt.Errorf("值 %s 在表 %s 的 %s 字段中不存在", str, table, column)
}
return nil
})
}
func (p Product) Validate() error {
return validation.ValidateStruct(&p,
validation.Field(&p.SKU,
validation.Required,
ExistsInTable("products", "sku"),
),
validation.Field(&p.CategoryID,
validation.Required,
validation.Min(1),
ExistsInTable("categories", "id"),
),
)
}
func main() {
product := Product{
SKU: "PROD-001",
CategoryID: 5,
}
if err := product.Validate(); err != nil {
fmt.Printf("验证失败: %v\n", err)
}
}
这些方案提供了类似Laravel的"exists"验证功能,可以根据具体需求选择适合的实现方式。