一个基于 Go 泛型的优雅环境变量管理库,提供类型安全的配置获取与转换功能。
envx 是一个轻量级、高性能的 Go 环境变量处理库。它利用 Go 1.18+ 引入的泛型特性,实现了类型安全的环境变量获取和自动转换功能,让配置管理变得更加简洁和安全。
go get github.com/cnb.cool/jun3.work/cloud/envx
或添加模块依赖(根据实际仓库地址调整):
# 在 go.mod 中添加
module your/project
go 1.24
require cnb.cool/jun3.work/cloud/envx v1.0.0
package main
import (
"fmt"
"cnb.cool/jun3.work/cloud/envx"
)
func main() {
// 获取整数类型环境变量
port := envx.Get[int]("PORT", 8080)
fmt.Printf("Port: %d\n", port)
// 获取字符串类型环境变量
name := envx.Get[string]("APP_NAME", "default")
fmt.Printf("Name: %s\n", name)
// 获取布尔类型环境变量
debug := envx.Get[bool]("DEBUG", false)
fmt.Printf("Debug: %v\n", debug)
// 获取浮点数类型环境变量
timeout := envx.Get[float64]("TIMEOUT", 30.0)
fmt.Printf("Timeout: %f\n", timeout)
}
安全地获取并转换环境变量值。
参数说明:
key: 环境变量键名defaultValue: 当键不存在或转换失败时返回的默认值支持类型:
int, int64, float64, float32boolstringtime.Time, envx.Time, envx.Date[]string, []float64, []int, []int64map[string]string, map[string]interface{}import (
"cnb.cool/jun3.work/cloud/envx"
"time"
)
// 获取时间类型
exp := envx.Get[envx.Time]("EXPIRY", envx.NowTime())
fmt.Println(exp.String()) // RFC3339 格式
// 获取日期类型
startDate := envx.Get[envx.Date]("START_DATE", envx.TodayDate())
fmt.Println(startDate.String()) // 2026-04-15 格式
// 时间操作
fmt.Println(exp.Unix()) // Unix 时间戳
fmt.Println(exp.Year()) // 年份
fmt.Println(exp.Month()) // 月份
// 日期操作
fmt.Println(startDate.AddDays(7)) // 7 天后
fmt.Println(startDate.IsWeekend()) // 是否周末
fmt.Println(startDate.IsWorkday()) // 是否工作日
import "cnb.cool/jun3.work/cloud/envx"
// 解析时长字符串
dur, err := envx.ConvertToDuration("1h30m")
if err != nil {
panic(err)
}
// 使用自定义 Duration 类型
duration := envx.NewDuration(dur)
fmt.Println(duration.String()) // 1h30m0s
fmt.Println(duration.Hours()) // 1.5
// 时长运算
newDur := duration.Add(envx.NewDuration(30 * time.Minute))
newDur = duration.Multiply(2)
newDur = duration.Divide(3)
// 时长比较
if duration.Greater(other) {
fmt.Println("当前时长更长")
}
// 时长格式化
fmt.Println(envx.DurationString(dur))
import "cnb.cool/jun3.work/cloud/envx"
// 创建数组
arr := envx.NewArray("apple", "banana", "cherry")
// 数组操作
arr = arr.Append("date") // 追加元素
arr = arr.Prepend("apricot") // 前置元素
arr = arr.RemoveValue("banana") // 移除元素
// 数组查询
if arr.Contains("apple") {
fmt.Println("包含苹果")
}
// 数组转换
arr = arr.Unique() // 去重
arr = arr.Sort() // 排序
arr = arr.Reverse() // 反转
// 数组信息
fmt.Println(arr.Len()) // 长度
fmt.Println(arr.Join(",")) // 连接成字符串
import "cnb.cool/jun3.work/cloud/envx"
// 创建映射
m := envx.NewMap("name", "John", "age", "30")
// 映射操作
m = m.Set("city", "Beijing") // 设置键值
value, exists := m.Get("name") // 获取值
m, removed := m.Remove("age") // 移除键
// 映射查询
if m.Contains("city") {
fmt.Println("包含城市信息")
}
// 映射信息
keys := m.Keys() // 获取所有键
values := m.Values() // 获取所有值
fmt.Println(m.Len()) // 映射大小
import "cnb.cool/jun3.work/cloud/envx"
// TryGet: 检查键是否存在
val, exists := envx.TryGet("DATABASE_URL")
if exists {
fmt.Println("数据库配置:", val)
}
// TryGetWithDefault: 尝试获取并转换,返回转换结果和成功标志
port, ok := envx.TryGetWithDefault[int]("PORT", 8080)
if ok {
fmt.Println("端口:", port)
} else {
fmt.Println("使用默认端口:", port)
}
true, 1, yes, y, on → truefalse, 0, no, n, off → false30s, 1m, 1h, 24hns, us, µs, ms, s, m, h1h30m, 2h45m30s2006-01-02T15:04:05Z07:002006-01-02T15:04:052006-01-02 15:04:052006-01-0201/02/2006, 2006/01/02envx/ ├── README.md # 项目文档(本文件) ├── go.mod # Go 模块定义 ├── converters.go # 类型转换函数和自定义类型定义 ├── get.go # 泛型 Get 函数实现 ├── utils.go # 工具函数和辅助功能 ├── get_test.go # 单元测试文件 └── .gitignore # Git 忽略规则
| 文件 | 说明 |
|---|---|
converters.go | 包含所有类型转换函数和自定义类型(Duration、Time、Date、Array、Map) |
get.go | 泛型 Get 函数实现,处理类型自动转换逻辑 |
utils.go | 工具函数(TryGet、TryGetWithDefault)和系统检测函数 |
get_test.go | 完整的单元测试,覆盖所有功能点 |
运行测试套件:
# 运行所有测试
go test -v
# 运行特定测试
go test -v -run TestGet_Int
# 生成测试覆盖率报告
go test -v -cover
# 查看覆盖率详情
go test -v -coverprofile=coverage.out && go tool cover -html=coverage.out
测试覆盖范围:
// 定义配置结构
type Config struct {
Port int
Debug bool
Timeout float64
Expiry envx.Time
Features envx.Array
}
// 加载配置
func LoadConfig() Config {
return Config{
Port: envx.Get[int]("PORT", 8080),
Debug: envx.Get[bool]("DEBUG", false),
Timeout: envx.Get[float64]("TIMEOUT", 30.0),
Expiry: envx.Get[envx.Time]("EXPIRY", envx.NowTime()),
Features: envx.Get[envx.Array]("FEATURES", envx.NewArray()),
}
}
// 使用 TryGetWithDefault 进行验证
if port, ok := envx.TryGetWithDefault[int]("PORT", 0); !ok || port <= 0 {
log.Fatal("无效的环境变量:PORT")
}
// 合理设置默认值,确保应用不会因缺失配置而崩溃
maxRetries := envx.Get[int]("MAX_RETRIES", 3) // 默认重试 3 次
logLevel := envx.Get[string]("LOG_LEVEL", "info") // 默认日志级别
欢迎贡献代码!以下是参与项目的方式:
git checkout -b feature/your-feature-namegit commit -m 'Add your feature'git push origin feature/your-feature-name<type>: <subject> [optional body]
常见类型:
feat: 新功能fix: 修复 bugdocs: 文档更新style: 代码格式调整refactor: 重构test: 测试相关chore: 构建/工具相关本项目采用 MIT 许可证。详见 LICENSE 文件。
MIT License 摘要:
- ✅ 允许商业使用
- ✅ 允许修改
- ✅ 允许分发
- ✅ 允许私有化
唯一要求:分发时需包含原许可证和版权声明
A: 泛型提供编译时类型检查,避免运行时类型错误,同时保持 API 的简洁性。
A: 自动返回默认值,不会抛出异常或 panic,确保应用稳定性。
A: 支持 RFC3339、ISO 8601 等多种常见时间格式,详见文档中的时间类型说明。
A: 目前支持预定义类型,如需自定义类型转换,可参考现有实现添加新类型支持。
注意: 本文档持续更新,请以仓库最新版本为准。