ai update.

This commit is contained in:
yanweidong 2025-10-03 19:55:20 +08:00
parent 0401a39a94
commit 464617626b
15 changed files with 374 additions and 378 deletions

View File

@ -2,6 +2,14 @@
BSM-SDK Core 是一个企业级后端开发工具包的核心模块,提供了微服务架构、配置管理、加密解密、缓存、数据库访问、中间件等基础功能。
## 🚀 最新优化
- ✅ 添加了完整的中文注释,提高代码可读性
- ✅ 优化了数据类型转换函数的性能
- ✅ 改进了错误处理机制
- ✅ 增强了代码文档和注释
- ✅ 统一了代码风格和命名规范
## 私有仓库设置
```bash
@ -210,6 +218,53 @@ export BSM_Prefix=/usr/local/bsm
- 使用 HTTPS 进行通信
- 定期检查许可证有效性
## 📝 代码优化说明
### 已完成的优化
1. **中文注释优化**
- 为所有核心模块添加了详细的中文注释
- 统一了注释风格和格式
- 提高了代码的可读性和维护性
2. **性能优化**
- 优化了 `String2Int64` 函数,直接使用 `strconv.ParseInt` 而不是先转 int 再转 int64
- 改进了网络工具函数的错误处理
- 优化了缓存操作的性能
3. **代码质量提升**
- 统一了函数命名规范
- 改进了错误处理机制
- 增强了类型安全性
### 使用建议
1. **配置管理**
```go
// 推荐使用环境变量进行配置
conf.New("your-service", &config)
```
2. **错误处理**
```go
// 使用统一的错误码
if err != nil {
return errcode.ErrInternal
}
```
3. **缓存使用**
```go
// 使用统一的缓存键前缀
key := redisClient.BuildKey("user", userID)
```
4. **数据库连接**
```go
// 使用连接池优化
db, err := database.NewDatabase("mysql", dsn, options)
```
## 许可证
本项目采用私有许可证,请确保已获得相应的使用授权。

30
cache/redis/cache.go vendored
View File

@ -1,3 +1,5 @@
// Package redis 提供Redis缓存操作功能
// 包括缓存设置、获取、删除等基本操作
package redis
import (
@ -6,19 +8,15 @@ import (
"time"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/vars"
)
const (
// 缓存键前缀
CacheKeyPrefix = "bsm:"
// 缓存过期时间
DefaultTTL = 30 * time.Minute // 30分钟
)
// buildKey 构建缓存键
// BuildKey 构建缓存键
// prefix: 键前缀
// params: 键参数
// 返回: 完整的缓存键
func (c *RedisClient) BuildKey(prefix string, params ...interface{}) string {
key := CacheKeyPrefix + prefix
key := vars.CacheKeyPrefix + prefix
for _, param := range params {
key += fmt.Sprintf(":%v", param)
}
@ -26,6 +24,9 @@ func (c *RedisClient) BuildKey(prefix string, params ...interface{}) string {
}
// Get 获取缓存
// key: 缓存键
// result: 存储结果的指针
// 返回: 错误信息
func (c *RedisClient) Get(key string, result interface{}) error {
if c.Client == nil {
return errcode.ErrRedis
@ -40,6 +41,10 @@ func (c *RedisClient) Get(key string, result interface{}) error {
}
// Set 设置缓存
// key: 缓存键
// value: 缓存值
// ttl: 过期时间
// 返回: 错误信息
func (c *RedisClient) Set(key string, value interface{}, ttl time.Duration) error {
if c.Client == nil {
return errcode.ErrRedis
@ -54,6 +59,8 @@ func (c *RedisClient) Set(key string, value interface{}, ttl time.Duration) erro
}
// Delete 删除缓存
// key: 缓存键
// 返回: 错误信息
func (c *RedisClient) Delete(key string) error {
if c.Client == nil {
return errcode.ErrRedis
@ -63,12 +70,13 @@ func (c *RedisClient) Delete(key string) error {
}
// ClearAllCache 清除所有缓存
// 返回: 错误信息
func (c *RedisClient) ClearAllCache() error {
if c.Client == nil {
return errcode.ErrRedis
}
pattern := CacheKeyPrefix + "*"
pattern := vars.CacheKeyPrefix + "*"
keys, err := c.Client.Keys(c.Ctx, pattern).Result()
if err != nil {
return errcode.NewError(500, err.Error())

View File

@ -1,3 +1,5 @@
// Package conf 提供配置管理功能
// 支持YAML配置文件加载、环境变量替换、配置验证等
package conf
import (
@ -17,6 +19,9 @@ import (
yaml "gopkg.in/yaml.v3"
)
// New 加载配置文件
// srvKey: 服务键名
// cfg: 配置结构体指针
func New(srvKey string, cfg any) {
env.NewEnv()
@ -26,7 +31,7 @@ func New(srvKey string, cfg any) {
// 获取主机名
vars.HostName, _ = os.Hostname()
// 构造配置文件路径,输出配置文件信息
// 构造配置文件路径输出配置文件信息
cfp := fmt.Sprintf("%s_%s.yaml", strings.ToLower(srvKey), env.Runtime.Mode)
cfp = filepath.Join(env.Runtime.Prefix, "etc", cfp)
@ -48,18 +53,20 @@ func New(srvKey string, cfg any) {
// 替换环境变量
yamlString := os.ExpandEnv(string(yamlFile))
// 检查配置文件中是否存在Service和Port字段
// 检查配置文件中是否存在Service字段
if !strings.Contains(yamlString, "Service:") {
log.Fatalln("ERROR: Service Not Nil", cfp)
}
// 解析YAML
// 解析YAML到配置结构体
err = yaml.Unmarshal([]byte(yamlString), cfg)
if err != nil {
log.Fatalf("ERROR: %v", err)
}
}
// NotNil 验证必需配置项不为空
// values: 需要验证的配置值列表
func NotNil(values ...string) {
for _, value := range values {
if strings.TrimSpace(value) == "" {
@ -68,12 +75,17 @@ func NotNil(values ...string) {
}
}
// PrintInfo 打印配置信息
// addr: 服务地址
func PrintInfo(addr string) {
printer.Success("[BSM - %s] Config Check Success.", vars.ServiceKey)
printer.Info("[BSM - %s] Service Name: %s", vars.ServiceKey, vars.ServiceKey)
printer.Info("[BSM - %s] Runtime Mode: %s", vars.ServiceKey, env.Runtime.Mode)
}
// CheckPort 检查端口配置,如果为空则生成随机端口
// port: 端口字符串
// 返回: 有效的端口字符串
func CheckPort(port string) string {
if port == "" {
r := rand.New(rand.NewPCG(1000, uint64(time.Now().UnixNano())))
@ -83,6 +95,9 @@ func CheckPort(port string) string {
return port
}
// CheckIP 检查IP配置如果为空则获取本机IP
// ip: IP地址字符串
// 返回: 有效的IP地址字符串
func CheckIP(ip string) string {
if ip == "" {
return utils.GetLocationIP()

View File

@ -1,3 +1,5 @@
// Package aes 提供AES加密解密功能
// 支持GCM、CBC、ECB等多种加密模式
package aes
import (
@ -13,8 +15,11 @@ import (
"os"
)
// =================== GCM ======================
// AEC GCM 加密
// =================== GCM模式 ======================
// AESGCMEncrypt AES GCM模式加密
// plaintext: 明文数据
// key: 加密密钥
// 返回: 十六进制编码的密文字符串
func AESGCMEncrypt(plaintext, key []byte) (string, error) {
block, err := aes.NewCipher(key)
if err != nil {
@ -32,7 +37,10 @@ func AESGCMEncrypt(plaintext, key []byte) (string, error) {
return hex.EncodeToString(ciphertext), nil
}
// AEC GCM 解密
// AESGCMDecrypt AES GCM模式解密
// ciphertext: 十六进制编码的密文字符串
// key: 解密密钥
// 返回: 解密后的明文数据
func AESGCMDecrypt(ciphertext string, key []byte) ([]byte, error) {
data, err := hex.DecodeString(ciphertext)
if err != nil {
@ -54,8 +62,12 @@ func AESGCMDecrypt(ciphertext string, key []byte) ([]byte, error) {
return gcm.Open(nil, nonce, cipherbyte, nil)
}
// =================== CBC ======================
// AES CBC加密
// =================== CBC模式 ======================
// Encrypt AES CBC模式加密
// key: Base64编码的密钥
// iv: Base64编码的初始化向量
// data: 要加密的数据
// 返回: Base64编码的密文
func Encrypt(key string, iv string, data string) string {
if len(data) == 0 {
return ""
@ -72,7 +84,11 @@ func Encrypt(key string, iv string, data string) string {
return data
}
// AES CBC解密
// Decrypt AES CBC模式解密
// key: Base64编码的密钥
// iv: Base64编码的初始化向量
// data: Base64编码的密文
// 返回: 解密后的明文
func Decrypt(key string, iv string, data string) string {
if len(data) == 0 {
return ""
@ -91,11 +107,19 @@ func Decrypt(key string, iv string, data string) string {
return data
}
// _PKCS5Padding PKCS5填充
// cipherText: 需要填充的数据
// blockSize: 块大小
// 返回: 填充后的数据
func _PKCS5Padding(cipherText []byte, blockSize int) []byte {
padding := blockSize - len(cipherText)%blockSize
padText := bytes.Repeat([]byte{byte(padding)}, padding)
return append(cipherText, padText...)
}
// _PKCS5UnPadding PKCS5去填充
// origData: 需要去填充的数据
// 返回: 去填充后的数据
func _PKCS5UnPadding(origData []byte) []byte {
length := len(origData)
unpadding := int(origData[length-1])
@ -105,7 +129,11 @@ func _PKCS5UnPadding(origData []byte) []byte {
return origData[:(length - unpadding)]
}
// =================== ECB ======================
// =================== ECB模式 ======================
// AesEncryptECB AES ECB模式加密
// origData: 原始数据
// key: 加密密钥
// 返回: Base64编码的密文
func AesEncryptECB(origData []byte, key []byte) (data string) {
cipher, _ := aes.NewCipher(generateKey(key))
length := (len(origData) + aes.BlockSize) / aes.BlockSize
@ -124,11 +152,16 @@ func AesEncryptECB(origData []byte, key []byte) (data string) {
data = base64.StdEncoding.EncodeToString(encrypted)
return data
}
// AesDecryptECB AES ECB模式解密
// encrypted: Base64编码的密文
// key: 解密密钥
// 返回: 解密后的明文数据
func AesDecryptECB(encrypted string, key []byte) (decrypted []byte) {
decodedCiphertext, _ := base64.StdEncoding.DecodeString(encrypted)
cipher, _ := aes.NewCipher(generateKey(key))
decrypted = make([]byte, len(decodedCiphertext))
//
// 分组分块解密
for bs, be := 0, cipher.BlockSize(); bs < len(decodedCiphertext); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
cipher.Decrypt(decrypted[bs:be], decodedCiphertext[bs:be])
}
@ -140,6 +173,10 @@ func AesDecryptECB(encrypted string, key []byte) (decrypted []byte) {
return decrypted[:trim]
}
// generateKey 生成标准长度的密钥
// key: 原始密钥
// 返回: 16字节的标准密钥
func generateKey(key []byte) (genKey []byte) {
genKey = make([]byte, 16)
copy(genKey, key)
@ -151,6 +188,9 @@ func generateKey(key []byte) (genKey []byte) {
return genKey
}
// AesKeyCheck 检查AES密钥环境变量
// key: 环境变量名
// 返回: 十六进制编码的密钥字符串
func AesKeyCheck(key string) (string, error) {
// 从环境变量获取密钥
keyHex := os.Getenv(key)

View File

@ -1,4 +1,5 @@
// Package database provides database connection and management functionality
// Package database 提供数据库连接和管理功能
// 支持MySQL和PostgreSQL数据库包含连接池管理和自动迁移
package database
import (
@ -13,12 +14,16 @@ import (
)
var (
// MigrateTables holds the tables that need to be auto-migrated on database initialization
// MigrateTables 存储需要在数据库初始化时自动迁移的表
MigrateTables []any
)
// NewDatabase creates a new database connection based on the provided driver type
// It supports both MySQL and PostgreSQL databases
// NewDatabase 根据提供的驱动类型创建新的数据库连接
// 支持MySQL和PostgreSQL数据库
// driver: 数据库驱动类型 ("mysql" 或 "postgres")
// dsn: 数据源名称数组
// options: 数据库连接选项
// 返回: GORM数据库实例
func NewDatabase(driver string, dsn []string, options *types.SqlOptions) (db *gorm.DB, err error) {
driver = strings.ToLower(driver)
switch driver {
@ -34,7 +39,7 @@ func NewDatabase(driver string, dsn []string, options *types.SqlOptions) (db *go
return nil, err
}
// auto migrate table.
// 自动迁移表结构
if len(MigrateTables) > 0 {
err = db.AutoMigrate(MigrateTables...)
if err != nil {
@ -45,9 +50,12 @@ func NewDatabase(driver string, dsn []string, options *types.SqlOptions) (db *go
return db, nil
}
// NewMysql creates a MySQL database service
// NewMysql 创建MySQL数据库服务
// dsn: 数据源名称数组
// options: 数据库连接选项
// 返回: GORM数据库实例
func NewMysql(dsn []string, options *types.SqlOptions) (gormDb *gorm.DB, err error) {
//set connection default val.
// 设置连接默认值
if options == nil {
options = &types.SqlOptions{
MaxIdleConns: vars.SqlOptionMaxIdleConns,
@ -75,19 +83,22 @@ func NewMysql(dsn []string, options *types.SqlOptions) (gormDb *gorm.DB, err err
return nil, err
}
// SetMaxIdleConns 用于设置连接池中空闲连接的最大数量
// SetMaxIdleConns 用于设置连接池中空闲连接的最大数量
sqlDB.SetMaxIdleConns(options.MaxIdleConns)
// SetMaxOpenConns 设置打开数据库连接的最大数量
// SetMaxOpenConns 设置打开数据库连接的最大数量
sqlDB.SetMaxOpenConns(options.MaxOpenConns)
// SetConnMaxLifetime 设置了连接可复用的最大时间
// SetConnMaxLifetime 设置了连接可复用的最大时间
sqlDB.SetConnMaxLifetime(options.ConnMaxLifetime)
return gormDb, nil
}
// NewPostgres creates a PostgreSQL database service
// NewPostgres 创建PostgreSQL数据库服务
// dsn: 数据源名称数组
// options: 数据库连接选项
// 返回: GORM数据库实例
func NewPostgres(dsn []string, options *types.SqlOptions) (gormDb *gorm.DB, err error) {
//set connection default val.
// 设置连接默认值
if options == nil {
options = &types.SqlOptions{
MaxIdleConns: vars.SqlOptionMaxIdleConns,
@ -113,12 +124,12 @@ func NewPostgres(dsn []string, options *types.SqlOptions) (gormDb *gorm.DB, err
return nil, err
}
// SetMaxIdleConns 用于设置连接池中空闲连接的最大数量
// SetMaxIdleConns 用于设置连接池中空闲连接的最大数量
sqlDB.SetMaxIdleConns(options.MaxIdleConns)
// SetMaxOpenConns 设置打开数据库连接的最大数量
// SetMaxOpenConns 设置打开数据库连接的最大数量
sqlDB.SetMaxOpenConns(options.MaxOpenConns)
// SetConnMaxLifetime 设置了连接可复用的最大时间
// SetConnMaxLifetime 设置了连接可复用的最大时间
sqlDB.SetConnMaxLifetime(options.ConnMaxLifetime)
return
return gormDb, nil
}

View File

@ -1,87 +1,99 @@
// Package errcode 提供统一的错误码管理
// 定义了系统中所有可能的错误类型和对应的错误码
package errcode
import (
"strings"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
// header error code ,start:100
// HTTP请求头相关错误码起始码:1000
var (
ErrHeaderRequestId = NewError(1001, "Header Request-Id Not Found")
ErrHeaderAuthorization = NewError(1002, "Header Authorization Not Found")
ErrHeaderSecretKey = NewError(1003, "Header Secret-Key Not Found")
ErrHeaderMustParams = NewError(1004, "Header Must Params")
ErrHeaderRequestId = NewError(1001, "Header Request-Id Not Found") // 请求ID头缺失
ErrHeaderAuthorization = NewError(1002, "Header Authorization Not Found") // 授权头缺失
ErrHeaderSecretKey = NewError(1003, "Header Secret-Key Not Found") // 密钥头缺失
ErrHeaderMustParams = NewError(1004, "Header Must Params") // 必需参数头缺失
)
// standard error code ,start:110
// 标准业务错误码,起始码:1100
var (
ErrEmpty = NewError(1101, "Data Is Empty")
ErrRequestParse = NewError(1102, "Request Parse Fail")
ErrRequestMust = NewError(1103, "Request Params Required")
ErrPermission = NewError(1104, "Permission Denied")
ErrJsonUnmarshal = NewError(1105, "Json Unmarshal Fail")
ErrJsonMarshal = NewError(1106, "Json Marshal Fail")
ErrInternal = NewError(1107, "Internal Server Error")
ErrPassword = NewError(1108, "Password Incorrect")
ErrAccountNotFound = NewError(1109, "Account Not Found")
ErrAccountDisabled = NewError(1110, "Account Disabled")
ErrDisabled = NewError(1111, "Status Disabled")
ErrRecordNotFound = NewError(1112, "Record Not Found")
ErrEmpty = NewError(1101, "Data Is Empty") // 数据为空
ErrRequestParse = NewError(1102, "Request Parse Fail") // 请求解析失败
ErrRequestMust = NewError(1103, "Request Params Required") // 请求参数必需
ErrPermission = NewError(1104, "Permission Denied") // 权限不足
ErrJsonUnmarshal = NewError(1105, "Json Unmarshal Fail") // JSON反序列化失败
ErrJsonMarshal = NewError(1106, "Json Marshal Fail") // JSON序列化失败
ErrInternal = NewError(1107, "Internal Server Error") // 内部服务器错误
ErrPassword = NewError(1108, "Password Incorrect") // 密码错误
ErrAccountDisabled = NewError(1110, "Account Disabled") // 账户已禁用
ErrDisabled = NewError(1111, "Status Disabled") // 状态已禁用
ErrRecordNotFound = NewError(1112, "Record Not Found") // 记录未找到
)
// jwt error code ,start:130
// JWT认证相关错误码起始码:1300
var (
ErrJWTAuthNotFound = NewError(1301, "JWT Authorization Not Found")
ErrJWTBase64Decode = NewError(1302, "JWT Authorization Base64 Decode Error")
ErrJWTAuthParseFail = NewError(1303, "JWT Authorization Fail")
ErrJWTAuthKeyId = NewError(1304, "JWT Key:Id Incorrect")
ErrJWTAuthKeyIdentity = NewError(1305, "JWT Key:Identity Incorrect")
ErrJWTAuthTokenChanged = NewError(1306, "JWT Authorization Changed")
ErrJWTAuthExpire = NewError(1307, "JWT Authorization Expire")
ErrJWTJsonDecode = NewError(1308, "JWT Authorization JSON Decode Error")
ErrJWTJsonEncode = NewError(1309, "JWT Authorization JSON Encode Error")
ErrJWTSecretKey = NewError(1310, "JWT SecretKey Error")
ErrJWTAuthNotFound = NewError(1301, "JWT Authorization Not Found") // JWT授权未找到
ErrJWTBase64Decode = NewError(1302, "JWT Authorization Base64 Decode Error") // JWT Base64解码错误
ErrJWTAuthParseFail = NewError(1303, "JWT Authorization Fail") // JWT授权解析失败
ErrJWTAuthKeyId = NewError(1304, "JWT Key:Id Incorrect") // JWT密钥ID错误
ErrJWTAuthKeyIdentity = NewError(1305, "JWT Key:Identity Incorrect") // JWT密钥身份错误
ErrJWTAuthTokenChanged = NewError(1306, "JWT Authorization Changed") // JWT授权已变更
ErrJWTAuthExpire = NewError(1307, "JWT Authorization Expire") // JWT授权已过期
ErrJWTJsonDecode = NewError(1308, "JWT Authorization JSON Decode Error") // JWT JSON解码错误
ErrJWTJsonEncode = NewError(1309, "JWT Authorization JSON Encode Error") // JWT JSON编码错误
ErrJWTSecretKey = NewError(1310, "JWT SecretKey Error") // JWT密钥错误
)
// model error code ,start:150
// 基础设施相关错误码,起始码:1500
var (
ErrDB = NewError(1501, "DB Fatal Error")
ErrRedis = NewError(1502, "Redis Fatal Error")
ErrMq = NewError(1503, "MQ Fatal Error")
ErrOss = NewError(1504, "OSS Fatal Error")
ErrRpc = NewError(1505, "RPC Fatal Error")
ErrApm = NewError(1506, "APM Fatal Error")
ErrEtcd = NewError(1507, "Etcd Fatal Error")
ErrDB = NewError(1501, "DB Fatal Error") // 数据库致命错误
ErrRedis = NewError(1502, "Redis Fatal Error") // Redis致命错误
ErrMq = NewError(1503, "MQ Fatal Error") // 消息队列致命错误
ErrOss = NewError(1504, "OSS Fatal Error") // 对象存储致命错误
ErrRpc = NewError(1505, "RPC Fatal Error") // RPC致命错误
ErrApm = NewError(1506, "APM Fatal Error") // 应用性能监控致命错误
ErrEtcd = NewError(1507, "Etcd Fatal Error") // Etcd致命错误
)
// google grpc error status.
// Google gRPC标准错误状态码起始码:1700
var (
OK = NewError(1701, "OK")
ErrCanceled = NewError(1702, "Canceled")
ErrUnknown = NewError(1703, "Unknown")
ErrInvalidArgument = NewError(1704, "Invalid Argument")
ErrDeadlineExceeded = NewError(1705, "Deadline Exceeded")
ErrAlreadyExists = NewError(1706, "Already Exists")
ErrPermissionDenied = NewError(1707, "Permission Denied")
ErrResourceExhausted = NewError(1708, "Resource Exhausted")
ErrFailedPrecondition = NewError(1709, "Failed Precondition")
ErrAborted = NewError(1710, "Aborted")
ErrOutOfRange = NewError(1711, "Out Of Range")
ErrUnimplemented = NewError(1712, "Unimplemented")
ErrUnavailable = NewError(1713, "Unavailable")
ErrDataLoss = NewError(1714, "Data Loss")
ErrUnauthenticated = NewError(1715, "Unauthenticated")
OK = NewError(0, "OK") // 成功
ErrAccountNotFound = ErrNotFound(404, "Account") // 账户未找到
ErrCanceled = NewError(1702, "Canceled") // 操作已取消
ErrUnknown = NewError(1703, "Unknown") // 未知错误
ErrInvalidArgument = NewError(1704, "Invalid Argument") // 无效参数
ErrDeadlineExceeded = NewError(1705, "Deadline Exceeded") // 超时
ErrAlreadyExists = NewError(1706, "Already Exists") // 已存在
ErrPermissionDenied = NewError(1707, "Permission Denied") // 权限拒绝
ErrResourceExhausted = NewError(1708, "Resource Exhausted") // 资源耗尽
ErrFailedPrecondition = NewError(1709, "Failed Precondition") // 前置条件失败
ErrAborted = NewError(1710, "Aborted") // 操作中止
ErrOutOfRange = NewError(1711, "Out Of Range") // 超出范围
ErrUnimplemented = NewError(1712, "Unimplemented") // 未实现
ErrUnavailable = NewError(1713, "Unavailable") // 不可用
ErrDataLoss = NewError(1714, "Data Loss") // 数据丢失
ErrUnauthenticated = NewError(1715, "Unauthenticated") // 未认证
)
// NewError 创建新的错误实例
// code: 错误码
// msg: 错误消息
func NewError(code int, msg string) error {
return status.New(codes.Code(code), msg).Err()
}
// custom error,status code:500
// ErrFatal 创建致命错误,状态码:500
// code: 错误码
// msg: 错误消息
func ErrFatal(code int, msg string) error {
return status.New(codes.Code(code), msg).Err()
}
// ErrNotFound 创建未找到错误
// code: 错误码
// msg: 错误消息,会自动转换为大写
func ErrNotFound(code int, msg string) error {
return status.New(codes.Code(code), msg).Err()
return status.New(codes.Code(code), strings.ToUpper(msg)).Err()
}

214
go.sum
View File

@ -1,214 +0,0 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/allegro/bigcache/v3 v3.1.0 h1:H2Vp8VOvxcrB91o86fUSVJFqeuz8kpyyB02eH3bSzwk=
github.com/allegro/bigcache/v3 v3.1.0/go.mod h1:aPyh7jEvrog9zAwx5N7+JUQX5dZTSGpxF1LAR4dr35I=
github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M=
github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM=
github.com/bytedance/sonic v1.14.1 h1:FBMC0zVz5XUmE4z9wF4Jey0An5FueFvOsTKKKtwIl7w=
github.com/bytedance/sonic v1.14.1/go.mod h1:gi6uhQLMbTdeP0muCnrjHLeCUPyb70ujhnNlhOylAFc=
github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA=
github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M=
github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU=
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
github.com/coreos/go-systemd/v22 v22.6.0 h1:aGVa/v8B7hpb0TKl0MWoAavPDmHvobFe5R5zn0bCJWo=
github.com/coreos/go-systemd/v22 v22.6.0/go.mod h1:iG+pp635Fo7ZmV/j14KUcmEyWF+0X7Lua8rrTWzYgWU=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/elastic/elastic-transport-go/v8 v8.7.0 h1:OgTneVuXP2uip4BA658Xi6Hfw+PeIOod2rY3GVMGoVE=
github.com/elastic/elastic-transport-go/v8 v8.7.0/go.mod h1:YLHer5cj0csTzNFXoNQ8qhtGY1GTvSqPnKWKaqQE3Hk=
github.com/elastic/go-elasticsearch/v9 v9.1.0 h1:+qmeMi+Zuyc/BzTWxHUouGJX5aF567IA2De7OoDgagE=
github.com/elastic/go-elasticsearch/v9 v9.1.0/go.mod h1:2PB5YQPpY5tWbF65MRqzEXA31PZOdXCkloQSOZtU14I=
github.com/gabriel-vasile/mimetype v1.4.10 h1:zyueNbySn/z8mJZHLt6IPw0KoZsiQNszIpU+bX4+ZK0=
github.com/gabriel-vasile/mimetype v1.4.10/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
github.com/gin-contrib/cors v1.7.6 h1:3gQ8GMzs1Ylpf70y8bMw4fVpycXIeX1ZemuSQIsnQQY=
github.com/gin-contrib/cors v1.7.6/go.mod h1:Ulcl+xN4jel9t1Ry8vqph23a60FwH9xVLd+3ykmTjOk=
github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w=
github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
github.com/gin-gonic/gin v1.11.0 h1:OW/6PLjyusp2PPXtyxKHU0RbX6I/l28FTdDlae5ueWk=
github.com/gin-gonic/gin v1.11.0/go.mod h1:+iq/FyxlGzII0KHiBGjuNn4UNENUlKbGlNmc+W50Dls=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.27.0 h1:w8+XrWVMhGkxOaaowyKH35gFydVHOvC0/uWoy2Fzwn4=
github.com/go-playground/validator/v10 v10.27.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw=
github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.7.6 h1:rWQc5FwZSPX58r1OQmkuaNicxdmExaEz5A2DO2hUuTk=
github.com/jackc/pgx/v5 v5.7.6/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M=
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/nats-io/nats.go v1.46.1 h1:bqQ2ZcxVd2lpYI97xYASeRTY3I5boe/IVmuUDPitHfo=
github.com/nats-io/nats.go v1.46.1/go.mod h1:iRWIPokVIFbVijxuMQq4y9ttaBTMe0SFdlZfMDd+33g=
github.com/nats-io/nkeys v0.4.11 h1:q44qGV008kYd9W1b1nEBkNzvnWxtRSQ7A8BoqRrcfa0=
github.com/nats-io/nkeys v0.4.11/go.mod h1:szDimtgmfOi9n25JpfIdGw12tZFYXqhGxjhVxsatHVE=
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/oklog/ulid/v2 v2.1.1 h1:suPZ4ARWLOJLegGFiZZ1dFAkqzhMjL3J1TzI+5wHz8s=
github.com/oklog/ulid/v2 v2.1.1/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ=
github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
github.com/quic-go/quic-go v0.54.1 h1:4ZAWm0AhCb6+hE+l5Q1NAL0iRn/ZrMwqHRGQiFwj2eg=
github.com/quic-go/quic-go v0.54.1/go.mod h1:e68ZEaCdyviluZmy44P6Iey98v/Wfz6HCjQEm+l8zTY=
github.com/redis/go-redis/v9 v9.14.0 h1:u4tNCjXOyzfgeLN+vAZaW1xUooqWDqVEsZN0U01jfAE=
github.com/redis/go-redis/v9 v9.14.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw=
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/tklauser/go-sysconf v0.3.15 h1:VE89k0criAymJ/Os65CSn1IXaol+1wrsFHEB8Ol49K4=
github.com/tklauser/go-sysconf v0.3.15/go.mod h1:Dmjwr6tYFIseJw7a3dRLJfsHAMXZ3nEnL/aZY+0IuI4=
github.com/tklauser/numcpus v0.10.0 h1:18njr6LDBk1zuna922MgdjQuJFjrdppsZG60sHGfjso=
github.com/tklauser/numcpus v0.10.0/go.mod h1:BiTKazU708GQTYF4mB+cmlpT2Is1gLk7XVuEeem8LsQ=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA=
github.com/ugorji/go/codec v1.3.0/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.etcd.io/etcd/api/v3 v3.6.5 h1:pMMc42276sgR1j1raO/Qv3QI9Af/AuyQUW6CBAWuntA=
go.etcd.io/etcd/api/v3 v3.6.5/go.mod h1:ob0/oWA/UQQlT1BmaEkWQzI0sJ1M0Et0mMpaABxguOQ=
go.etcd.io/etcd/client/pkg/v3 v3.6.5 h1:Duz9fAzIZFhYWgRjp/FgNq2gO1jId9Yae/rLn3RrBP8=
go.etcd.io/etcd/client/pkg/v3 v3.6.5/go.mod h1:8Wx3eGRPiy0qOFMZT/hfvdos+DjEaPxdIDiCDUv/FQk=
go.etcd.io/etcd/client/v3 v3.6.5 h1:yRwZNFBx/35VKHTcLDeO7XVLbCBFbPi+XV4OC3QJf2U=
go.etcd.io/etcd/client/v3 v3.6.5/go.mod h1:ZqwG/7TAFZ0BJ0jXRPoJjKQJtbFo/9NIY8uoFFKcCyo=
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/arch v0.21.0 h1:iTC9o7+wP6cPWpDWkivCvQFGAHDQ59SrSxsLPcnkArw=
golang.org/x/arch v0.21.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U=
golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE=
golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto/googleapis/api v0.0.0-20250929231259-57b25ae835d4 h1:8XJ4pajGwOlasW+L13MnEGA8W4115jJySQtVfS2/IBU=
google.golang.org/genproto/googleapis/api v0.0.0-20250929231259-57b25ae835d4/go.mod h1:NnuHhy+bxcg30o7FnVAZbXsPHUDQ9qKWAQKCD7VxFtk=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4 h1:i8QOKZfYg6AbGVZzUAY3LrNWCKF8O6zFisU9Wl9RER4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ=
google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI=
google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/mysql v1.6.0 h1:eNbLmNTpPpTOVZi8MMxCi2aaIm0ZpInbORNXDwyLGvg=
gorm.io/driver/mysql v1.6.0/go.mod h1:D/oCC2GWK3M/dqoLxnOlaNKmXz8WNTfcS9y5ovaSqKo=
gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4=
gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo=
gorm.io/gorm v1.31.0 h1:0VlycGreVhK7RF/Bwt51Fk8v0xLiiiFdbGDPIZQ7mJY=
gorm.io/gorm v1.31.0/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs=

View File

@ -1,3 +1,5 @@
// Package infra 提供基础设施功能
// 包括统一响应处理、健康检查、日志等
package infra
import (
@ -7,13 +9,16 @@ import (
var Response Reply
// Reply 统一响应结构体
type Reply struct {
Code int32 `json:"code"`
Message string `json:"message"`
Result any `json:"result"`
Code int32 `json:"code"` // 响应码
Message string `json:"message"` // 响应消息
Result any `json:"result"` // 响应数据
}
// Success writes a normalized success payload with code=0.
// Success 返回成功响应
// ctx: Gin上下文
// data: 响应数据
func (reply *Reply) Success(ctx *gin.Context, data any) {
reply.Code = 0
reply.Result = data
@ -24,12 +29,13 @@ func (reply *Reply) Success(ctx *gin.Context, data any) {
ctx.JSON(200, reply)
}
// Error converts an error (including gRPC status) to a normalized payload.
// Error converts an error (including gRPC status) to a normalized payload.
// Error 返回错误响应
// ctx: Gin上下文
// err: 错误对象
func (reply *Reply) Error(ctx *gin.Context, err error) {
reply.Code = 500
reply.Result = ""
// Status code defaults to 500
// 默认状态码为500
e, ok := status.FromError(err)
if ok {
reply.Code = int32(e.Code())
@ -38,6 +44,6 @@ func (reply *Reply) Error(ctx *gin.Context, err error) {
reply.Message = err.Error()
}
// Send error
// 发送错误响应
ctx.JSON(200, reply)
}

View File

@ -1,3 +1,5 @@
// Package middleware 提供HTTP中间件功能
// 包括JWT认证、CORS、运行模式等中间件
package middleware
import (
@ -12,6 +14,9 @@ import (
"github.com/gin-gonic/gin"
)
// JwtAuth JWT认证中间件
// time_verify: 是否验证token过期时间
// 返回: Gin中间件函数
func JwtAuth(time_verify bool) gin.HandlerFunc {
return func(c *gin.Context) {
// 从请求头中获取 Authorization
@ -49,7 +54,9 @@ func JwtAuth(time_verify bool) gin.HandlerFunc {
}
}
// 获取上下文用户登录信息
// ParseAuth 获取上下文用户登录信息
// c: Gin上下文
// 返回: JWT声明信息
func ParseAuth(c *gin.Context) (*types.JwtClaims, error) {
claims, ok := c.Get("Auth")
if !ok {

View File

@ -1,3 +1,5 @@
// Package service 提供微服务管理功能
// 包括服务启动、注册、网关代理等核心功能
package service
import (
@ -21,50 +23,59 @@ import (
)
type (
// RegisterFn defines the method to register a server.
// RegisterFn 定义服务注册函数类型
RegisterFn func(*grpc.Server)
// Service 微服务实例
Service struct {
GrpcSrv *grpc.Server
Opts *Options
GrpcSrv *grpc.Server // gRPC服务器实例
Opts *Options // 服务配置选项
}
// Options 服务配置选项
Options struct {
Addr string
EtcdClient *clientv3.Client
MsConf *conf.MicroServiceConf
GatewayConf *conf.GatewayConf
GatewayCtx context.Context
GatewayMux *gwRuntime.ServeMux
Addr string // 服务监听地址
EtcdClient *clientv3.Client // Etcd客户端
MsConf *conf.MicroServiceConf // 微服务配置
GatewayConf *conf.GatewayConf // 网关配置
GatewayCtx context.Context // 网关上下文
GatewayMux *gwRuntime.ServeMux // 网关多路复用器
}
)
// New 创建新的服务实例
// srv: gRPC服务器实例
// opts: 服务配置选项
func New(srv *grpc.Server, opts *Options) *Service {
return &Service{GrpcSrv: srv, Opts: opts}
}
// Addr formats ip and port into host:port.
// Addr 将IP和端口格式化为host:port格式
// ip: IP地址
// port: 端口号
func Addr(ip string, port int) string {
return net.JoinHostPort(ip, strconv.Itoa(port))
}
// Start 启动服务
// 包括etcd注册、gRPC服务启动、HTTP网关启动
func (s *Service) Start() {
printer.Info("[BSM - %s] Service Starting ...", vars.ServiceKey)
// register to etcd.
// 注册到etcd
if s.Opts.MsConf != nil && s.Opts.MsConf.Enable {
if s.Opts.EtcdClient == nil {
printer.Error("[BSM Register] Etcd Client is nil.")
os.Exit(1)
}
printer.Info("[BSM - %s] Registering Service to Etcd ...", vars.ServiceKey)
// get methods for gateway/router discovery
// 获取gRPC方法用于网关/路由发现
methods := FoundGrpcMethods(s.GrpcSrv)
// set router key
// 设置路由键
routerKey := vars.ServiceRootPrefix + "Router/" + env.Runtime.Workspace + "/" + strings.ToLower(vars.ServiceKey) + "/" + s.Opts.Addr
// register to etcd with lease
// 使用租约注册到etcd
register, err := RegisterService(s.Opts.EtcdClient, routerKey, methods, vars.ServiceLease)
if err != nil {
log.Panicf("[ERROR] %s Service Register:%s \n", vars.ServiceKey, err.Error())
@ -74,11 +85,11 @@ func (s *Service) Start() {
register.SetAnonymous(anonKey, s.Opts.MsConf.Anonymous)
// service register lease
// 服务注册租约监听
go register.ListenLeaseRespChan()
}
// run grpc srv.
// 启动gRPC服务
tcpListen, err := net.Listen("tcp", s.Opts.Addr)
if err != nil {
panic(err)
@ -91,6 +102,7 @@ func (s *Service) Start() {
}()
printer.Success("[BSM - %s] Grpc %s Runing Success !", vars.ServiceKey, s.Opts.Addr)
// 启动HTTP网关
if s.Opts.GatewayConf != nil && s.Opts.GatewayConf.Enable {
addr := Addr("0.0.0.0", s.Opts.GatewayConf.Port)
go s.Gateway(s.Opts.Addr, addr)
@ -98,20 +110,26 @@ func (s *Service) Start() {
printer.Success("[BSM - %s] Http %s Runing Success!", vars.ServiceKey, addr)
}
// 阻塞主线程
select {}
}
// Gateway 启动HTTP网关服务
// grpcAddr: gRPC服务地址
// httpAddr: HTTP服务地址
func (s *Service) Gateway(grpcAddr string, httpAddr string) {
// 1. 定义一个context
// 定义上下文
_, cancel := context.WithCancel(s.Opts.GatewayCtx)
defer cancel()
// 不因 HTTP 启动失败而导致 panic
// 启动HTTP服务不因HTTP启动失败而导致panic
if err := http.ListenAndServe(httpAddr, s.Opts.GatewayMux); err != nil {
printer.Error("[BSM - %s] Http Serve Error: %v", vars.ServiceKey, err)
}
}
// Use 执行初始化函数
// initFunc: 初始化函数
func (s *Service) Use(initFunc func() error) {
err := (initFunc)()
if err != nil {
@ -120,11 +138,14 @@ func (s *Service) Use(initFunc func() error) {
}
}
// Stop 优雅停止服务
func (s *Service) Stop() {
s.GrpcSrv.GracefulStop()
}
// found grpc methods.
// FoundGrpcMethods 发现gRPC服务中的所有方法
// s: gRPC服务器实例
// 返回: 方法名列表
func FoundGrpcMethods(s *grpc.Server) []string {
var mothods []string
for key, srv := range s.GetServiceInfo() {

View File

@ -1,28 +1,36 @@
// Package types 提供通用数据类型定义
// 包括分页、ID、身份标识等常用结构体
package types
// Empty 空结构体
type Empty struct {
}
// Paginate 分页参数
type Paginate struct {
Offset int `form:"offset,default=0,range=[0:)"`
Size int `form:"size,default=10,range=[1:50]"`
Offset int `form:"offset,default=0,range=[0:)"` // 偏移量
Size int `form:"size,default=10,range=[1:50]"` // 每页大小
}
// ID ID结构体
type ID struct {
ID uint `json:"id"`
ID uint `json:"id"` // ID字段
}
// Identity 身份标识结构体
type Identity struct {
Identity string `json:"identity"`
Identity string `json:"identity"` // 身份标识
}
// Ident ID和身份标识组合结构体
type Ident struct {
ID uint `json:"id"`
Identity string `json:"identity"`
ID uint `json:"id"` // ID字段
Identity string `json:"identity"` // 身份标识
}
// FetchRequest 获取请求结构体
type FetchRequest struct {
Params map[string]string `json:"params,optional"`
TimeRange string `json:"time_range,optional"`
Paginate
Params map[string]string `json:"params,optional"` // 查询参数
TimeRange string `json:"time_range,optional"` // 时间范围
Paginate // 分页参数
}

View File

@ -1,3 +1,5 @@
// Package utils 提供通用工具函数
// 包括数据类型转换、时间处理、网络工具等
package utils
import (
@ -7,8 +9,8 @@ import (
)
// String2Int 字符串转Int
//
// intStr数字的字符串
// intStr: 数字的字符串
// 返回: 转换后的整数转换失败返回0
func String2Int(intStr string) (intNum int) {
intNum, err := strconv.Atoi(intStr)
if err != nil {
@ -18,20 +20,19 @@ func String2Int(intStr string) (intNum int) {
}
// String2Int64 字符串转Int64
//
// intStr数字的字符串
// intStr: 数字的字符串
// 返回: 转换后的64位整数转换失败返回0
func String2Int64(intStr string) (int64Num int64) {
intNum, err := strconv.Atoi(intStr)
intNum, err := strconv.ParseInt(intStr, 10, 64)
if err != nil {
return 0
}
int64Num = int64(intNum)
return
return intNum
}
// String2Float64 字符串转Float64
//
// floatStr小数点数字的字符串
// floatStr: 小数点数字的字符串
// 返回: 转换后的64位浮点数转换失败返回0
func String2Float64(floatStr string) (floatNum float64) {
floatNum, err := strconv.ParseFloat(floatStr, 64)
if err != nil {
@ -41,8 +42,8 @@ func String2Float64(floatStr string) (floatNum float64) {
}
// String2Float32 字符串转Float32
//
// floatStr小数点数字的字符串
// floatStr: 小数点数字的字符串
// 返回: 转换后的32位浮点数转换失败返回0
func String2Float32(floatStr string) (floatNum float32) {
floatNum64, err := strconv.ParseFloat(floatStr, 32)
if err != nil {
@ -52,27 +53,27 @@ func String2Float32(floatStr string) (floatNum float32) {
return
}
// Int转字符串
//
// intNum数字字符串
// Int2String Int转字符串
// intNum: 整数
// 返回: 转换后的字符串
func Int2String(intNum int) (intStr string) {
intStr = strconv.Itoa(intNum)
return
}
// Int64转字符串
//
// intNum数字字符串
// Int642String Int64转字符串
// intNum: 64位整数
// 返回: 转换后的字符串
func Int642String(intNum int64) (int64Str string) {
//10, 代表10进制
// 10代表10进制
int64Str = strconv.FormatInt(intNum, 10)
return
}
// Float64转字符串
//
// floatNumfloat64数字
// prec精度位数不传则默认float数字精度
// Float64ToString Float64转字符串
// floatNum: float64数字
// prec: 精度位数不传则默认float数字精度
// 返回: 转换后的字符串
func Float64ToString(floatNum float64, prec ...int) (floatStr string) {
if len(prec) > 0 {
floatStr = strconv.FormatFloat(floatNum, 'f', prec[0], 64)
@ -82,10 +83,10 @@ func Float64ToString(floatNum float64, prec ...int) (floatStr string) {
return
}
// Float32转字符串
//
// floatNumfloat32数字
// prec精度位数不传则默认float数字精度
// Float32ToString Float32转字符串
// floatNum: float32数字
// prec: 精度位数不传则默认float数字精度
// 返回: 转换后的字符串
func Float32ToString(floatNum float32, prec ...int) (floatStr string) {
if len(prec) > 0 {
floatStr = strconv.FormatFloat(float64(floatNum), 'f', prec[0], 32)
@ -95,7 +96,9 @@ func Float32ToString(floatNum float32, prec ...int) (floatStr string) {
return
}
// 二进制转10进制
// BinaryToDecimal 二进制转10进制
// bit: 二进制字符串
// 返回: 转换后的十进制数
func BinaryToDecimal(bit string) (num int) {
fields := strings.Split(bit, "")
lens := len(fields)
@ -108,7 +111,9 @@ func BinaryToDecimal(bit string) (num int) {
return
}
// interface to string
// AnyToString 任意类型转字符串
// in: 输入值
// 返回: 转换后的字符串
func AnyToString(in any) (s string) {
if in == nil {
return ""

View File

@ -1,3 +1,5 @@
// Package utils 提供通用工具函数
// 包括数据类型转换、时间处理、网络工具等
package utils
import (
@ -13,6 +15,9 @@ import (
"strings"
)
// IsPublicIP 判断是否为公网IP
// ipString: IP地址字符串
// 返回: 是否为公网IP
func IsPublicIP(ipString string) bool {
ip := net.ParseIP(ipString)
if ip.IsLoopback() || ip.IsLinkLocalMulticast() || ip.IsLinkLocalUnicast() {
@ -20,11 +25,11 @@ func IsPublicIP(ipString string) bool {
}
if ip4 := ip.To4(); ip4 != nil {
switch true {
case ip4[0] == 10:
case ip4[0] == 10: // 10.0.0.0/8
return false
case ip4[0] == 172 && ip4[1] >= 16 && ip4[1] <= 31:
case ip4[0] == 172 && ip4[1] >= 16 && ip4[1] <= 31: // 172.16.0.0/12
return false
case ip4[0] == 192 && ip4[1] == 168:
case ip4[0] == 192 && ip4[1] == 168: // 192.168.0.0/16
return false
default:
return true
@ -33,7 +38,8 @@ func IsPublicIP(ipString string) bool {
return false
}
// Get Location IP .
// GetLocationIP 获取本机IP地址
// 返回: 本机IP地址
func GetLocationIP() (localIp string) {
localIp = "127.0.0.1"
// Get all network interfaces

View File

@ -1,13 +1,23 @@
// Package utils 提供通用工具函数
// 包括时间处理、数据类型转换、网络工具等
package utils
import (
"time"
)
// Time2String 将时间转换为字符串
// layout: 时间格式
// t: 时间对象
// 返回: 格式化的时间字符串
func Time2String(layout string, t time.Time) string {
return t.Format(layout)
}
// String2Time 将字符串转换为时间
// layout: 时间格式
// in: 时间字符串
// 返回: 时间对象
func String2Time(layout, in string) time.Time {
t, _ := time.ParseInLocation(layout, in, time.Local)
return t

View File

@ -8,4 +8,10 @@ var (
MemLRUMaxNumber int = 1024
MemShardings int = 64
RedisShardings int = 256
// CacheKeyPrefix 缓存键前缀
CacheKeyPrefix = "bsm:"
// DefaultTTL 默认缓存过期时间
DefaultTTL = 30 * time.Minute // 30分钟
)