package utils import ( "crypto/rand" "encoding/hex" "fmt" "regexp" "strconv" "strings" "time" "github.com/gin-gonic/gin" "github.com/google/uuid" "golang.org/x/crypto/bcrypt" ) // HashPassword 对密码进行哈希加密 func HashPassword(password string) (string, error) { bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) return string(bytes), err } // CheckPasswordHash 验证密码哈希 func CheckPasswordHash(password, hash string) bool { err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) return err == nil } // GenerateUUID 生成UUID func GenerateUUID() string { return uuid.New().String() } // GenerateRandomString 生成指定长度的随机字符串 func GenerateRandomString(length int) (string, error) { bytes := make([]byte, length/2) if _, err := rand.Read(bytes); err != nil { return "", err } return hex.EncodeToString(bytes), nil } // IsValidEmail 验证邮箱格式 func IsValidEmail(email string) bool { pattern := `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$` regex := regexp.MustCompile(pattern) return regex.MatchString(email) } // IsValidPhone 验证手机号格式(中国大陆) func IsValidPhone(phone string) bool { pattern := `^1[3-9]\d{9}$` regex := regexp.MustCompile(pattern) return regex.MatchString(phone) } // IsStrongPassword 验证密码强度 func IsStrongPassword(password string) bool { if len(password) < 8 { return false } // 至少包含一个数字 hasNumber := regexp.MustCompile(`[0-9]`).MatchString(password) // 至少包含一个小写字母 hasLower := regexp.MustCompile(`[a-z]`).MatchString(password) // 至少包含一个大写字母 hasUpper := regexp.MustCompile(`[A-Z]`).MatchString(password) // 至少包含一个特殊字符 hasSpecial := regexp.MustCompile(`[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]`).MatchString(password) return hasNumber && hasLower && hasUpper && hasSpecial } // GetPaginationParams 从请求中获取分页参数 func GetPaginationParams(c *gin.Context) (page, pageSize int) { pageStr := c.DefaultQuery("page", "1") pageSizeStr := c.DefaultQuery("page_size", "20") page, err := strconv.Atoi(pageStr) if err != nil || page < 1 { page = 1 } pageSize, err = strconv.Atoi(pageSizeStr) if err != nil || pageSize < 1 || pageSize > 100 { pageSize = 20 } return page, pageSize } // CalculateOffset 计算数据库查询偏移量 func CalculateOffset(page, pageSize int) int { return (page - 1) * pageSize } // CalculateTotalPages 计算总页数 func CalculateTotalPages(total, pageSize int) int { if total == 0 { return 0 } return (total + pageSize - 1) / pageSize } // StringToInt 字符串转整数,带默认值 func StringToInt(str string, defaultValue int) int { if str == "" { return defaultValue } value, err := strconv.Atoi(str) if err != nil { return defaultValue } return value } // StringToBool 字符串转布尔值,带默认值 func StringToBool(str string, defaultValue bool) bool { if str == "" { return defaultValue } value, err := strconv.ParseBool(str) if err != nil { return defaultValue } return value } // TrimSpaces 去除字符串前后空格 func TrimSpaces(str string) string { return strings.TrimSpace(str) } // FormatTime 格式化时间 func FormatTime(t time.Time) string { return t.Format("2006-01-02 15:04:05") } // ParseTime 解析时间字符串 func ParseTime(timeStr string) (time.Time, error) { return time.Parse("2006-01-02 15:04:05", timeStr) } // GetUserIDFromContext 从上下文中获取用户ID func GetUserIDFromContext(c *gin.Context) (int64, bool) { userID, exists := c.Get("user_id") if !exists { return 0, false } if id, ok := userID.(int64); ok { return id, true } return 0, false } // SetUserIDToContext 设置用户ID到上下文 func SetUserIDToContext(c *gin.Context, userID int64) { c.Set("user_id", userID) } // Int64ToString 将int64转换为string func Int64ToString(i int64) string { return strconv.FormatInt(i, 10) } // StringToInt64 将string转换为int64 func StringToInt64(str string) (int64, error) { return strconv.ParseInt(str, 10, 64) } // Contains 检查切片是否包含指定元素 func Contains(slice []string, item string) bool { for _, s := range slice { if s == item { return true } } return false } // RemoveDuplicates 去除字符串切片中的重复元素 func RemoveDuplicates(slice []string) []string { keys := make(map[string]bool) result := []string{} for _, item := range slice { if !keys[item] { keys[item] = true result = append(result, item) } } return result } // GenerateFileName 生成文件名 func GenerateFileName(originalName string) string { ext := "" if dotIndex := strings.LastIndex(originalName, "."); dotIndex != -1 { ext = originalName[dotIndex:] } return fmt.Sprintf("%d_%s%s", time.Now().Unix(), GenerateUUID()[:8], ext) } // GetClientIP 获取客户端IP地址 func GetClientIP(c *gin.Context) string { // 尝试从X-Forwarded-For头获取 if ip := c.GetHeader("X-Forwarded-For"); ip != "" { if index := strings.Index(ip, ","); index != -1 { return strings.TrimSpace(ip[:index]) } return strings.TrimSpace(ip) } // 尝试从X-Real-IP头获取 if ip := c.GetHeader("X-Real-IP"); ip != "" { return strings.TrimSpace(ip) } // 使用RemoteAddr return c.ClientIP() }