主要变更: - 采用 go-zero 框架替代 Gin,提升开发效率 - 重构项目结构,API 文件模块化组织 - 将 model 移至 api/internal/model 目录 - 移除 common 包,改为标准 pkg 目录结构 - 实现统一的仓储模式,支持配置驱动数据库切换 - 简化测试策略,专注 API 集成测试 - 更新 CLAUDE.md 文档,提供详细的开发指导 技术栈更新: - 框架: Gin → go-zero v1.6.0+ - 代码生成: 引入 goctl 工具 - 架构模式: 四层架构 → go-zero 三层架构 (Handler→Logic→Model) - 项目布局: 遵循 Go 社区标准和 go-zero 最佳实践
128 lines
3.1 KiB
Go
128 lines
3.1 KiB
Go
package utils
|
||
|
||
import (
|
||
"regexp"
|
||
"strings"
|
||
"unicode"
|
||
)
|
||
|
||
// IsValidEmail 验证邮箱格式
|
||
func IsValidEmail(email string) bool {
|
||
emailRegex := regexp.MustCompile(`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`)
|
||
return emailRegex.MatchString(email)
|
||
}
|
||
|
||
// IsValidUsername 验证用户名格式
|
||
func IsValidUsername(username string) bool {
|
||
// 用户名长度3-20,只能包含字母、数字、下划线
|
||
if len(username) < 3 || len(username) > 20 {
|
||
return false
|
||
}
|
||
|
||
usernameRegex := regexp.MustCompile(`^[a-zA-Z0-9_]+$`)
|
||
return usernameRegex.MatchString(username)
|
||
}
|
||
|
||
// IsValidPassword 验证密码强度
|
||
func IsValidPassword(password string) bool {
|
||
// 密码长度至少6位
|
||
if len(password) < 6 {
|
||
return false
|
||
}
|
||
|
||
// 检查是否包含字母和数字
|
||
hasLetter := false
|
||
hasNumber := false
|
||
|
||
for _, char := range password {
|
||
if unicode.IsLetter(char) {
|
||
hasLetter = true
|
||
}
|
||
if unicode.IsNumber(char) {
|
||
hasNumber = true
|
||
}
|
||
}
|
||
|
||
return hasLetter && hasNumber
|
||
}
|
||
|
||
// IsValidSlug 验证slug格式
|
||
func IsValidSlug(slug string) bool {
|
||
// slug只能包含小写字母、数字和连字符
|
||
if len(slug) == 0 || len(slug) > 100 {
|
||
return false
|
||
}
|
||
|
||
slugRegex := regexp.MustCompile(`^[a-z0-9-]+$`)
|
||
return slugRegex.MatchString(slug) && !strings.HasPrefix(slug, "-") && !strings.HasSuffix(slug, "-")
|
||
}
|
||
|
||
// IsValidHexColor 验证十六进制颜色代码
|
||
func IsValidHexColor(color string) bool {
|
||
colorRegex := regexp.MustCompile(`^#[a-fA-F0-9]{6}$`)
|
||
return colorRegex.MatchString(color)
|
||
}
|
||
|
||
// IsValidURL 验证URL格式
|
||
func IsValidURL(url string) bool {
|
||
urlRegex := regexp.MustCompile(`^https?://[^\s/$.?#].[^\s]*$`)
|
||
return urlRegex.MatchString(url)
|
||
}
|
||
|
||
// SanitizeString 清理字符串,移除HTML标签和特殊字符
|
||
func SanitizeString(input string) string {
|
||
// 移除HTML标签
|
||
htmlRegex := regexp.MustCompile(`<[^>]*>`)
|
||
cleaned := htmlRegex.ReplaceAllString(input, "")
|
||
|
||
// 移除多余的空白字符
|
||
whitespaceRegex := regexp.MustCompile(`\s+`)
|
||
cleaned = whitespaceRegex.ReplaceAllString(cleaned, " ")
|
||
|
||
return strings.TrimSpace(cleaned)
|
||
}
|
||
|
||
// ValidateImageFormat 验证图片格式
|
||
func ValidateImageFormat(filename string) bool {
|
||
allowedExtensions := []string{".jpg", ".jpeg", ".png", ".gif", ".webp"}
|
||
lowerFilename := strings.ToLower(filename)
|
||
|
||
for _, ext := range allowedExtensions {
|
||
if strings.HasSuffix(lowerFilename, ext) {
|
||
return true
|
||
}
|
||
}
|
||
|
||
return false
|
||
}
|
||
|
||
// ValidateFileSize 验证文件大小(字节)
|
||
func ValidateFileSize(size int64, maxSizeMB int64) bool {
|
||
maxSizeBytes := maxSizeMB * 1024 * 1024
|
||
return size <= maxSizeBytes && size > 0
|
||
}
|
||
|
||
// NormalizeString 标准化字符串(去空格、转小写)
|
||
func NormalizeString(s string) string {
|
||
return strings.ToLower(strings.TrimSpace(s))
|
||
}
|
||
|
||
// ContainsOnlyASCII 检查字符串是否只包含ASCII字符
|
||
func ContainsOnlyASCII(s string) bool {
|
||
for _, char := range s {
|
||
if char > 127 {
|
||
return false
|
||
}
|
||
}
|
||
return true
|
||
}
|
||
|
||
// Contains 检查切片是否包含指定元素
|
||
func Contains(slice []string, item string) bool {
|
||
for _, s := range slice {
|
||
if s == item {
|
||
return true
|
||
}
|
||
}
|
||
return false
|
||
} |