#validator - 資料驗證
#概述
validator 模組為 Go 結構體提供全面的資料驗證,支援多種語言環境和自定義驗證規則。它為常見資料類型提供內置驗證器,並允許註冊自定義驗證器。
#核心函數
#Struct()
使用結構體標籤驗證結構體資料。
func Struct(s interface{}) error參數:
s- 要驗證的結構體指針
返回值:
- 如果驗證失敗,返回驗證錯誤
- 如果驗證通過,返回 nil
示例:
type User struct {
Name string `validate:"required,min=2,max=50"`
Email string `validate:"required,email"`
Age int `validate:"min=0,max=150"`
}
user := User{
Name: "John Doe",
Email: "john@example.com",
Age: 25,
}
if err := validator.Struct(&user); err != nil {
fmt.Printf("驗證失敗: %v\n", err)
}#Var()
使用驗證標籤驗證單個變數。
func Var(field interface{}, tag string) error參數:
field- 要驗證的值tag- 驗證規則
返回值:
- 如果驗證失敗,返回驗證錯誤
- 如果驗證通過,返回 nil
示例:
if err := validator.Var("john@example.com", "required,email"); err != nil {
fmt.Printf("無效的電子郵件: %v\n", err)
}
if err := validator.Var(25, "min=0,max=150"); err != nil {
fmt.Printf("無效的年齡: %v\n", err)
}#SetLocale()
設置錯誤訊息的語言環境。
func SetLocale(locale string)支援的語言環境:
en- 英語(預設)zh-CN- 簡體中文zh-TW- 繁體中文fr- 法語de- 德語es- 西班牙語it- 義大利語ja- 日語ko- 韓語pt- 葡萄牙語ru- 俄語
示例:
validator.SetLocale("zh-TW")
err := validator.Struct(&user)
// 錯誤訊息將是繁體中文#RegisterValidation()
註冊自定義驗證規則。
func RegisterValidation(tag string, fn ValidatorFunc) error參數:
tag- 驗證標籤名稱fn- 驗證函數
返回值:
- 如果註冊失敗,返回錯誤
示例:
func validatePassword(fl validator.FieldLevel) bool {
password := fl.Field().String()
return len(password) >= 8 &&
strings.ContainsAny(password, "0123456789") &&
strings.ContainsAny(password, "ABCDEFGHIJKLMNOPQRSTUVWXYZ") &&
strings.ContainsAny(password, "abcdefghijklmnopqrstuvwxyz")
}
validator.RegisterValidation("strong_password", validatePassword)
type User struct {
Password string `validate:"required,strong_password"`
}#RegisterTranslation()
為驗證錯誤註冊自定義翻譯。
func RegisterTranslation(locale, tag, translation string)參數:
locale- 語言環境代碼tag- 驗證標籤translation- 翻譯模板
示例:
validator.RegisterTranslation("en", "custom_tag", "{field} 必須是自定義的")
type User struct {
Field string `validate:"custom_tag"`
}#內置驗證規則
#必填欄位
type User struct {
Name string `validate:"required"`
Email string `validate:"required,email"`
}#字串驗證
type User struct {
Username string `validate:"required,min=3,max=20"`
Bio string `validate:"max=500"`
Website string `validate:"url"`
}#數值驗證
type Product struct {
Price float64 `validate:"required,gt=0"`
Stock int `validate:"min=0,max=10000"`
Rating float64 `validate:"min=0,max=5"`
}#日期驗證
type Event struct {
StartDate time.Time `validate:"required"`
EndDate time.Time `validate:"required,gtfield=StartDate"`
}#自定義規則
type User struct {
Mobile string `validate:"required,mobile"`
IDCard string `validate:"required,idcard"`
BankCard string `validate:"required,bankcard"`
Name string `validate:"required,chinese_name"`
Email string `validate:"required,email"`
URL string `validate:"required,url"`
IP string `validate:"required,ipv4"`
MAC string `validate:"required,mac"`
JSON string `validate:"required,json"`
UUID string `validate:"required,uuid"`
}#使用模式
#完整的使用者驗證
type User struct {
Name string `validate:"required,min=2,max=50,chinese_name"`
Email string `validate:"required,email"`
Mobile string `validate:"required,mobile"`
IDCard string `validate:"required,idcard"`
BankCard string `validate:"required,bankcard"`
Age int `validate:"required,min=18,max=120"`
Password string `validate:"required,min=8,strong_password"`
}
func CreateUser(user *User) error {
// 設置語言環境以獲取繁體中文錯誤訊息
validator.SetLocale("zh-TW")
// 驗證使用者
if err := validator.Struct(user); err != nil {
return fmt.Errorf("驗證失敗: %w", err)
}
// 在資料庫中建立使用者
return db.Create(user)
}#條件驗證
type Order struct {
PaymentMethod string `validate:"required,oneof=credit_card paypal bank_transfer"`
CardNumber string `validate:"required_if=PaymentMethod credit_card,credit_card"`
PayPalEmail string `validate:"required_if=PaymentMethod paypal,email"`
}
func CreateOrder(order *Order) error {
if err := validator.Struct(order); err != nil {
return err
}
// 處理訂單
return nil
}#帶參數的自定義驗證器
func validatePasswordComplexity(fl validator.FieldLevel) bool {
password := fl.Field().String()
param := fl.Param() // 從標籤獲取參數
minLen := 8
if param != "" {
minLen, _ = strconv.Atoi(param)
}
if len(password) < minLen {
return false
}
hasUpper := strings.ContainsAny(password, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
hasLower := strings.ContainsAny(password, "abcdefghijklmnopqrstuvwxyz")
hasDigit := strings.ContainsAny(password, "0123456789")
return hasUpper && hasLower && hasDigit
}
validator.RegisterValidation("password_complexity", validatePasswordComplexity)
type User struct {
Password string `validate:"required,password_complexity=12"`
}#高級功能
#自定義驗證器
type CustomValidator struct {
validator *validator.Validate
}
func NewCustomValidator() *CustomValidator {
v := validator.New()
// 註冊自定義驗證器
v.RegisterValidation("custom_rule", func(fl validator.FieldLevel) bool {
value := fl.Field().String()
// 自定義驗證邏輯
return len(value) > 0
})
return &CustomValidator{validator: v}
}
func (cv *CustomValidator) Validate(s interface{}) error {
return cv.validator.Struct(s)
}#多語言支援
func ValidateUser(user *User, lang string) error {
// 根據使用者偏好設置語言環境
validator.SetLocale(lang)
if err := validator.Struct(user); err != nil {
// 錯誤訊息將使用指定的語言
return err
}
return nil
}
// 示例用法
ValidateUser(user, "en") // 英文錯誤訊息
ValidateUser(user, "zh-TW") // 繁體中文錯誤訊息
ValidateUser(user, "fr") // 法文錯誤訊息#結構體級別驗證
type User struct {
Password string `validate:"required,min=8"`
Confirm string `validate:"required,eqfield=Password"`
}
func (u User) Validate() error {
return validator.Struct(&u)
}#最佳實踐
#驗證標籤
type User struct {
// 好:具體且清晰的驗證
Name string `validate:"required,min=2,max=50"`
Email string `validate:"required,email"`
// 壞:過於通用
Name string `validate:"required"`
Email string `validate:"required"`
}#錯誤處理
func HandleValidation(err error) error {
if err == nil {
return nil
}
// 檢查是否為驗證錯誤
if validationErrors, ok := err.(validator.ValidationErrors); ok {
var messages []string
for _, e := range validationErrors {
messages = append(messages, fmt.Sprintf(
"%s: %s",
e.Field(),
e.Tag(),
))
}
return fmt.Errorf("驗證錯誤: %s", strings.Join(messages, "; "))
}
return err
}#效能
// 好:重用驗證器實例
var v = validator.New()
func ValidateUser(user *User) error {
return v.Struct(user)
}
// 避免:每次都建立新驗證器
func ValidateUser(user *User) error {
v := validator.New() // 昂貴
return v.Struct(user)
}