包函数
包级便捷函数提供简洁的 API,适合大多数使用场景。这些函数使用全局默认加载器,所有函数都是线程安全的。
初始化要求
全局默认加载器必须通过 Load() 或 LoadWithConfig() 显式初始化,不会在首次调用时自动创建。若未初始化,函数行为如下:
Get*函数(GetString、GetInt、GetBool等):返回传入的默认值(或零值)Lookup:返回("", false)Keys/All/Len/GetSecure:返回nil/0Set/Delete/Validate/ParseInto:返回ErrNotInitialized
加载函数
Load
func Load(filenames ...string) error加载环境变量文件并应用到系统环境。
参数:
filenames- 文件路径列表。未提供时不加载任何文件,需显式传入".env"来加载默认文件。
返回:
error- 加载错误
行为:
- 创建新的 Loader 实例并设为默认加载器
- 自动应用到系统环境(
os.Environ) - 后加载的文件覆盖先加载的
- 返回
ErrAlreadyInitialized如果默认加载器已初始化 - 支持多格式(.env、JSON、YAML)
// 加载 .env 文件
if err := env.Load(".env"); err != nil {
log.Fatal(err)
}
// 加载指定文件(按顺序,后覆盖前)
if err := env.Load(".env", ".env.local", "config.json"); err != nil {
log.Fatal(err)
}
// JSON/YAML 嵌套结构支持点号访问
// config.json: {"database": {"host": "localhost", "port": 5432}}
env.Load("config.json")
host := env.GetString("database.host") // "localhost"
port := env.GetInt("database.port") // 5432键名解析
所有获取函数都支持智能键名解析,提供灵活的访问方式。
解析规则
1. 精确匹配(优先)
// .env: APP_NAME=myapp
name := env.GetString("APP_NAME") // "myapp"2. 大写转换(简单键)
// 对于不含点号的键,自动尝试大写版本
name := env.GetString("app_name") // 查找 app_name -> APP_NAME3. 点号路径解析(嵌套键)
// JSON: {"app": {"name": "myapp"}}
// 存储为:APP_NAME=myapp
// 以下方式都能访问到该值
name := env.GetString("APP_NAME") // 扁平化键名(推荐)
name := env.GetString("app.name") // 点号路径(自动转换)
name := env.GetString("APP.NAME") // 大写点号路径路径转换表
| 输入键名 | 存储键名 |
|---|---|
"database.host" | "DATABASE_HOST" |
"db.port" | "DB_PORT" |
"servers.0.host" | "SERVERS_0_HOST" |
"app.config.name" | "APP_CONFIG_NAME" |
索引访问
数组元素可通过索引访问,或回退到逗号分隔值:
// JSON: {"servers": [{"host": "a.com"}, {"host": "b.com"}]}
// 存储为:SERVERS_0_HOST=a.com, SERVERS_1_HOST=b.com
host0 := env.GetString("servers.0.host") // "a.com"
host1 := env.GetString("servers.1.host") // "b.com"
// 如果键不存在但存在逗号分隔的基础值
// HOSTS=localhost,example.com
host0 := env.GetString("hosts.0") // "localhost" (从逗号分隔值解析)获取值函数
GetString
func GetString(key string, defaultValue ...string) string获取字符串值。支持点号路径解析。
参数:
key- 键名(支持精确匹配、大写转换、点号路径)defaultValue- 可选默认值
返回:
string- 值或默认值(未找到且无默认值时返回空字符串)
// 基本用法
host := env.GetString("HOST", "localhost")
// 点号路径访问(JSON/YAML 嵌套结构)
dbHost := env.GetString("database.host", "localhost")
appName := env.GetString("app.name")
// 无默认值时返回空字符串
value := env.GetString("NON_EXISTENT") // ""GetInt
func GetInt(key string, defaultValue ...int64) int64获取整数值。自动转换字符串为整数。支持点号路径解析。
参数:
key- 键名(支持点号路径)defaultValue- 可选默认值,类型为int64
返回:
int64- 值或默认值(未找到且无默认值时返回 0)
port := env.GetInt("PORT", 8080)
maxConn := env.GetInt("database.max_connections", 10)
// 无默认值时返回 0
value := env.GetInt("NON_EXISTENT") // 0GetBool
func GetBool(key string, defaultValue ...bool) bool获取布尔值。支持点号路径解析。
- 真值(不区分大小写):
true,1,yes,on,enabled - 假值(不区分大小写):
false,0,no,off,disabled
参数:
key- 键名(支持点号路径)defaultValue- 可选默认值
返回:
bool- 值或默认值(未找到且无默认值时返回 false)
debug := env.GetBool("DEBUG", false)
cacheEnabled := env.GetBool("cache.enabled", true)
// 无默认值时返回 false
value := env.GetBool("NON_EXISTENT") // falseGetUint64
func GetUint64(key string, defaultValue ...uint64) uint64获取无符号整数值。支持点号路径解析。
参数:
key- 键名(支持点号路径)defaultValue- 可选默认值,类型为uint64
返回:
uint64- 值或默认值(未找到且无默认值时返回 0)
port := env.GetUint64("PORT", 8080)
maxSize := env.GetUint64("MAX_SIZE", 1024)
// 无默认值时返回 0
value := env.GetUint64("NON_EXISTENT") // 0GetFloat64
func GetFloat64(key string, defaultValue ...float64) float64获取浮点数值。支持点号路径解析。
参数:
key- 键名(支持点号路径)defaultValue- 可选默认值,类型为float64
返回:
float64- 值或默认值(未找到且无默认值时返回 0)
rate := env.GetFloat64("RATE", 0.5)
threshold := env.GetFloat64("THRESHOLD")
// 无默认值时返回 0
value := env.GetFloat64("NON_EXISTENT") // 0GetDuration
func GetDuration(key string, defaultValue ...time.Duration) time.Duration获取时间间隔值。支持点号路径解析。
支持的格式:
300ms- 毫秒1.5s- 秒2m30s- 分钟 + 秒1h30m- 小时 + 分钟
参数:
key- 键名(支持点号路径)defaultValue- 可选默认值
返回:
time.Duration- 值或默认值(未找到且无默认值时返回 0)
timeout := env.GetDuration("TIMEOUT", 30*time.Second)
interval := env.GetDuration("INTERVAL", 5*time.Minute)
// 无默认值时返回 0
value := env.GetDuration("NON_EXISTENT") // 0GetSecure
func GetSecure(key string) *SecureValue获取安全值(用于敏感数据)。
参数:
key- 键名
返回:
*SecureValue- 安全值包装器,键不存在或加载器不可用返回 nil
secret := env.GetSecure("API_KEY")
if secret != nil {
defer secret.Release()
value := secret.Reveal() // 明文值(仅在需要时调用)
masked := secret.Masked() // 用于日志:[SECURE:32 bytes]
}重要
使用后必须调用 Release() 或 Close() 释放资源。推荐使用 defer 确保释放。
详见
SecureValue API 获取完整 API 文档。
GetSlice[T]
func GetSlice[T sliceElement](key string, defaultValue ...[]T) []T泛型函数,获取切片值。
支持的类型: string, int, int64, uint, uint64, bool, float64, time.Duration
注意: 这是一个泛型函数,不是 Loader 的方法。如需从指定 Loader 实例获取切片,使用 GetSliceFrom[T]。
解析顺序:
- 优先查找索引键
KEY_0,KEY_1,KEY_2... - 若无索引键,则按逗号分隔解析
KEY的值 - 支持点号路径解析
参数:
key- 键名defaultValue- 可选默认值
返回:
[]T- 切片值
// 索引键格式(推荐)
// HOSTS_0=localhost
// HOSTS_1=example.com
hosts := env.GetSlice[string]("HOSTS") // ["localhost", "example.com"]
// 逗号分隔格式
// PORTS=80,443,8080
ports := env.GetSlice[int64]("PORTS", []int64{80}) // [80, 443, 8080]
// 浮点数切片
rates := env.GetSlice[float64]("RATES", []float64{0.1, 0.2})
// 布尔切片
flags := env.GetSlice[bool]("FLAGS")
// Duration 切片
timeouts := env.GetSlice[time.Duration]("TIMEOUTS")
// 无符号整数切片
ports := env.GetSlice[uint]("PORTS")
port64s := env.GetSlice[uint64]("PORTS")
// int 类型
portInts := env.GetSlice[int]("PORTS")
// 无默认值时返回 nil
value := env.GetSlice[string]("NON_EXISTENT") // nilGetSliceFrom[T]
func GetSliceFrom[T sliceElement](loader *Loader, key string, defaultValue ...[]T) []T从指定 Loader 实例获取切片值。这是独立的泛型函数(不是 Loader 方法)。
参数:
loader- Loader 实例指针(如果为 nil,返回默认值)key- 键名defaultValue- 可选默认值
返回:
[]T- 切片值
支持的类型: string, int, int64, uint, uint64, bool, float64, time.Duration
loader, _ := env.New(cfg)
defer loader.Close()
// 从 loader 实例获取切片
hosts := env.GetSliceFrom[string](loader, "HOSTS")
ports := env.GetSliceFrom[int64](loader, "PORTS", []int64{80})
// 也支持 int、uint、uint64 类型
portsInt := env.GetSliceFrom[int](loader, "PORTS")
portsUint := env.GetSliceFrom[uint](loader, "PORTS")
portsUint64 := env.GetSliceFrom[uint64](loader, "PORTS")区别
GetSlice[T]- 使用默认加载器的包级函数GetSliceFrom[T]- 指定 Loader 实例的泛型函数(Go 不支持泛型方法)
查询函数
Lookup
func Lookup(key string) (string, bool)检查键是否存在并获取值。支持点号路径解析。
参数:
key- 键名(支持点号路径)
返回:
string- 值(首尾空白已移除)bool- 是否存在
value, exists := env.Lookup("API_KEY")
if !exists {
// 键不存在
}
// 点号路径
if value, exists := env.Lookup("database.host"); exists {
fmt.Println(value)
}Keys
func Keys() []string获取所有键名。
返回:
[]string- 键名列表,加载器不可用时返回 nil
keys := env.Keys()
for _, key := range keys {
fmt.Println(key)
}All
func All() map[string]string获取所有键值对。
返回:
map[string]string- 键值映射,加载器不可用时返回 nil
all := env.All()
for key, value := range all {
fmt.Printf("%s=%s\n", key, value)
}Len
func Len() int获取变量数量。
返回:
int- 变量数量,加载器不可用时返回 0
count := env.Len()
fmt.Printf("已加载 %d 个环境变量\n", count)设置和删除
Set
func Set(key, value string) error设置环境变量。
参数:
key- 键名value- 值
返回:
error- 设置错误
错误类型:
*ValidationError- 键名格式无效(Field="key")*SecurityError- 键被禁止(可用errors.Is(err, env.ErrSecurityViolation)匹配)ErrInvalidValue- 值无效(当ValidateValues为 true 时,值包含空字节、控制字符等不安全内容)ErrClosed- 加载器已关闭
if err := env.Set("CUSTOM_KEY", "value"); err != nil {
// 可能是 *SecurityError(禁止键)或 *ValidationError(键格式)
}Delete
func Delete(key string) error删除环境变量。
参数:
key- 键名
返回:
error- 删除错误
if err := env.Delete("TEMP_KEY"); err != nil {
panic(err)
}验证和映射
Validate
func Validate() error验证必需键是否存在。需要在 Config 中设置 RequiredKeys。
返回:
error- 验证错误
// 需要先配置 RequiredKeys(通过自定义加载器)
cfg := env.ProductionConfig()
cfg.RequiredKeys = []string{"DB_HOST", "API_KEY"}
loader, _ := env.New(cfg)
loader.LoadFiles(".env")
if err := loader.Validate(); err != nil {
// 缺少必需键
}ParseInto
func ParseInto(v any) error将环境变量映射到结构体。
参数:
v- 结构体指针
返回:
error- 映射错误
type Config struct {
Host string `env:"HOST" envDefault:"localhost"`
Port int64 `env:"PORT" envDefault:"8080"`
}
var cfg Config
if err := env.ParseInto(&cfg); err != nil {
panic(err)
}结构体标签:
| 标签 | 说明 |
|---|---|
env:"KEY" | 映射到指定键 |
env:"-" | 忽略此字段 |
envDefault:"value" | 默认值 |
切片字段默认按逗号 , 分隔(分隔符前后空格自动去除),无自定义分隔符标签。
详见
结构体映射 获取完整指南。
工具函数
ResetDefaultLoader
func ResetDefaultLoader() error重置全局默认加载器。主要用于测试场景。
返回:
error- 关闭旧加载器的错误(如果存在);如果之前没有加载器或关闭成功则返回 nil
行为:
- 通过
atomic.Pointer.Swap原子地将默认加载器交换为 nil - 在持有
defaultMu锁的状态下关闭旧的加载器(关闭完成才释放锁,确保重置过程的原子性) - 重置后允许通过
Load()或LoadWithConfig()创建新的默认加载器
func TestMain(m *testing.M) {
if err := env.ResetDefaultLoader(); err != nil {
log.Printf("warning: failed to reset loader: %v", err)
}
os.Exit(m.Run())
}
func TestSomething(t *testing.T) {
if err := env.ResetDefaultLoader(); err != nil {
t.Logf("warning: %v", err)
}
defer env.ResetDefaultLoader()
// ... 测试代码
}注意
此函数是并发安全的,但仅在测试或启动时调用以避免意外行为。
LoadWithConfig
func LoadWithConfig(cfg Config) error使用自定义配置初始化默认加载器。
参数:
cfg- 自定义配置
返回:
error- 初始化错误
行为:
- 设置包级默认加载器(
GetString、GetInt等函数使用) - 强制
AutoApply = true(无论 cfg 中的设置) - 返回
ErrAlreadyInitialized如果默认加载器已初始化
与 Load 的区别:
Load()- 仅接受文件名列表,使用默认配置LoadWithConfig()- 接受完整 Config,支持所有配置选项
cfg := env.DefaultConfig()
cfg.Filenames = []string{".env.production"}
cfg.OverwriteExisting = true
if err := env.LoadWithConfig(cfg); err != nil {
log.Fatal(err)
}
// 现在可以使用包级函数
port := env.GetInt("PORT", 8080)注意
此函数会强制将 cfg.AutoApply 设为 true,确保变量应用到系统环境。如需控制应用时机,请使用 New() 创建独立实例。
序列化函数
Marshal
func Marshal(data any, format ...FileFormat) (string, error)将数据序列化为指定格式的字符串。支持 map[string]string 或结构体作为输入。
接口集成: 如果输入类型实现了 Marshaler 接口,优先调用 MarshalEnv() 方法进行序列化。
参数:
data- 要序列化的数据(map 或结构体)format- 可选格式,默认FormatEnv
返回:
string- 序列化后的字符串(键已排序)error- 序列化错误
支持格式:
FormatEnv(默认) - .env 格式FormatJSON- JSON 格式FormatYAML- YAML 格式
// map 转 .env 格式
mapData := map[string]string{"HOST": "localhost", "PORT": "8080"}
envStr, _ := env.Marshal(mapData)
// HOST=localhost
// PORT=8080
// map 转 JSON 格式(数字字符串原样输出为数字,键按字母序排列)
jsonStr, _ := env.Marshal(mapData, env.FormatJSON)
// {
// "HOST": "localhost",
// "PORT": 8080
// }
// 结构体转 .env 格式
type Config struct {
Host string `env:"HOST"`
Port string `env:"PORT"`
}
envStr, _ := env.Marshal(Config{Host: "localhost", Port: "8080"})UnmarshalMap
func UnmarshalMap(data string, format ...FileFormat) (map[string]string, error)将格式化字符串解析为 map。支持自动格式检测。
参数:
data- 格式化字符串format- 可选格式,默认FormatEnv;使用FormatAuto自动检测
返回:
map[string]string- 解析后的键值对error- 解析错误
// .env 格式
m, _ := env.UnmarshalMap("HOST=localhost\nPORT=8080")
// JSON 格式(嵌套结构会被扁平化)
m, _ := env.UnmarshalMap(`{"database": {"host": "localhost"}}`, env.FormatJSON)
// m["DATABASE_HOST"] = "localhost"
// 自动检测格式
m, _ := env.UnmarshalMap(jsonString, env.FormatAuto)UnmarshalStruct
func UnmarshalStruct(data string, v any, format ...FileFormat) error将格式化字符串解析并填充到结构体。
参数:
data- 格式化字符串v- 结构体指针format- 可选格式,默认FormatEnv
返回:
error- 解析错误
type Config struct {
Host string `env:"SERVER_HOST"`
Port int `env:"SERVER_PORT"`
}
var cfg Config
err := env.UnmarshalStruct("SERVER_HOST=localhost\nSERVER_PORT=8080", &cfg)
// cfg.Host = "localhost", cfg.Port = 8080
// 从 JSON 解析
err = env.UnmarshalStruct(`{"server": {"host": "localhost"}}`, &cfg, env.FormatJSON)UnmarshalInto
func UnmarshalInto(data map[string]string, v any) error将 map 填充到结构体。支持 env 和 envDefault 标签。
接口集成: 如果目标类型实现了 Unmarshaler 接口,优先调用 UnmarshalEnv(data) 方法。
参数:
data- 键值对映射v- 结构体指针
返回:
error- 填充错误
type Config struct {
Host string `env:"HOST" envDefault:"localhost"`
Port int `env:"PORT" envDefault:"8080"`
}
data := map[string]string{"HOST": "example.com"}
var cfg Config
err := env.UnmarshalInto(data, &cfg)
// cfg.Host = "example.com", cfg.Port = 8080 (使用默认值)MarshalStruct
func MarshalStruct(v any) (map[string]string, error)将结构体转换为 map。支持 env 标签指定键名。
接口集成: 如果输入类型实现了 Marshaler 接口,优先调用 MarshalEnv() 方法。
参数:
v- 结构体或结构体指针
返回:
map[string]string- 键值对映射error- 转换错误
type Config struct {
Host string `env:"SERVER_HOST"`
Port int `env:"SERVER_PORT"`
}
cfg := Config{Host: "localhost", Port: 8080}
m, _ := env.MarshalStruct(cfg)
// m["SERVER_HOST"] = "localhost"
// m["SERVER_PORT"] = "8080"IsMarshalError
func IsMarshalError(err error) bool检查错误是否为序列化/反序列化错误。
参数:
err- 要检查的错误
返回:
bool- 是否为 MarshalError 类型
_, err := env.MarshalStruct(invalidData)
if env.IsMarshalError(err) {
// 处理序列化错误
}完整示例
package main
import (
"fmt"
"log"
"time"
"github.com/cybergodev/env"
)
type AppConfig struct {
Host string `env:"APP_HOST" envDefault:"0.0.0.0"`
Port int64 `env:"APP_PORT" envDefault:"8080"`
Debug bool `env:"DEBUG" envDefault:"false"`
Timeout time.Duration `env:"TIMEOUT" envDefault:"30s"`
Hosts []string `env:"HOSTS"`
}
func main() {
// 加载配置文件
if err := env.Load(".env"); err != nil {
log.Printf("Warning: %v", err)
}
// 读取单个值
host := env.GetString("APP_HOST", "localhost")
port := env.GetInt("APP_PORT", 8080)
debug := env.GetBool("DEBUG", false)
timeout := env.GetDuration("TIMEOUT", 30*time.Second)
fmt.Printf("Server: %s:%d\n", host, port)
fmt.Printf("Debug: %v, Timeout: %v\n", debug, timeout)
// 敏感数据
secret := env.GetSecure("API_KEY")
if secret != nil {
defer secret.Release()
fmt.Printf("API Key length: %d\n", secret.Length())
}
// 结构体映射
var cfg AppConfig
if err := env.ParseInto(&cfg); err != nil {
log.Fatal(err)
}
fmt.Printf("Config: %+v\n", cfg)
// 所有变量
fmt.Printf("Loaded %d variables\n", env.Len())
}相关文档
- Loader API - Loader 实例方法
- Config API - 配置选项
- SecureValue API - 安全值处理
- 结构体映射 - 结构体映射指南