194 lines
3.7 KiB
Go
194 lines
3.7 KiB
Go
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
|
|
} |