Golang中类似Laravel的功能有哪些

Golang中类似Laravel的功能有哪些 在验证器(validator)中,当尝试验证一条记录并检查某个值是否存在于特定表中时,Golang 中与 Laravel 的 “exist” 功能等效的是什么?

2 回复

你好。

等价于对数据库的原始查询。

更多关于Golang中类似Laravel的功能有哪些的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在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"验证功能,可以根据具体需求选择适合的实现方式。

回到顶部