package utils import ( "crypto/rand" "encoding/hex" "fmt" "net" "strconv" "strings" "time" ) // GenerateID 生成唯一 ID func GenerateID() string { b := make([]byte, 16) rand.Read(b) return hex.EncodeToString(b) } // GenerateNodeID 生成节点 ID func GenerateNodeID(prefix string) string { return fmt.Sprintf("%s_%s_%d", prefix, GenerateID()[:8], time.Now().Unix()) } // FormatBytes 格式化字节数 func FormatBytes(bytes int64) string { const unit = 1024 if bytes < unit { return fmt.Sprintf("%d B", bytes) } div, exp := int64(unit), 0 for n := bytes / unit; n >= unit; n /= unit { div *= unit exp++ } return fmt.Sprintf("%.1f %ciB", float64(bytes)/float64(div), "KMGTPE"[exp]) } // ParseBytes 解析字节字符串 func ParseBytes(s string) (int64, error) { s = strings.TrimSpace(s) s = strings.ToUpper(s) multiplier := int64(1) if strings.HasSuffix(s, "KB") { multiplier = 1024 s = strings.TrimSuffix(s, "KB") } else if strings.HasSuffix(s, "MB") { multiplier = 1024 * 1024 s = strings.TrimSuffix(s, "MB") } else if strings.HasSuffix(s, "GB") { multiplier = 1024 * 1024 * 1024 s = strings.TrimSuffix(s, "GB") } else if strings.HasSuffix(s, "TB") { multiplier = 1024 * 1024 * 1024 * 1024 s = strings.TrimSuffix(s, "TB") } value, err := strconv.ParseInt(strings.TrimSpace(s), 10, 64) if err != nil { return 0, err } return value * multiplier, nil } // FormatDuration 格式化持续时间 func FormatDuration(d time.Duration) string { if d < time.Second { return fmt.Sprintf("%dms", d.Milliseconds()) } if d < time.Minute { return fmt.Sprintf("%.1fs", d.Seconds()) } if d < time.Hour { return fmt.Sprintf("%.1fm", d.Minutes()) } return fmt.Sprintf("%.1fh", d.Hours()) } // IsPrivateIP 检查是否为私有 IP func IsPrivateIP(ip string) bool { ipAddr := net.ParseIP(ip) if ipAddr == nil { return false } privateBlocks := []string{ "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16", "127.0.0.0/8", } for _, block := range privateBlocks { _, cidr, _ := net.ParseCIDR(block) if cidr.Contains(ipAddr) { return true } } return false } // IsValidPort 检查端口是否有效 func IsValidPort(port int) bool { return port > 0 && port <= 65535 } // ParseHostPort 解析主机:端口 func ParseHostPort(addr string) (host string, port int, err error) { parts := strings.Split(addr, ":") if len(parts) != 2 { return "", 0, fmt.Errorf("invalid address format") } host = parts[0] port, err = strconv.Atoi(parts[1]) if err != nil { return "", 0, fmt.Errorf("invalid port: %v", err) } if !IsValidPort(port) { return "", 0, fmt.Errorf("port out of range") } return host, port, nil } // Contains 检查字符串切片是否包含某元素 func Contains(slice []string, item string) bool { for _, s := range slice { if s == item { return true } } return false } // Unique 去重 func Unique(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 } // Retry 重试函数 func Retry(fn func() error, maxAttempts int, delay time.Duration) error { var lastErr error for i := 0; i < maxAttempts; i++ { if err := fn(); err != nil { lastErr = err if i < maxAttempts-1 { time.Sleep(delay) } continue } return nil } return fmt.Errorf("after %d attempts, last error: %v", maxAttempts, lastErr) } // Min 返回最小值 func Min(a, b int) int { if a < b { return a } return b } // Max 返回最大值 func Max(a, b int) int { if a > b { return a } return b } // Clamp 将值限制在范围内 func Clamp(value, min, max int) int { if value < min { return min } if value > max { return max } return value }