golang环境变量解析与结构体映射插件库env的使用
Golang环境变量解析与结构体映射插件库env的使用
env
是一个用于Go的环境变量工具包,它提供了简单的函数来获取和设置环境变量,包括支持将环境变量解组到结构体中,支持嵌套结构、默认值和必填字段。
功能特性
- 基本获取/设置:简单的获取、设置和取消设置环境变量的函数
- 类型转换:将环境变量作为不同类型(int、bool、float)获取的函数
- 回退值:支持在环境变量未设置时使用回退值
- 解组:使用结构体标签将环境变量加载到结构体中
- 嵌套结构体:支持嵌套结构体前缀来分组环境变量
安装
go get github.com/syntaqx/env
基本使用
package main
import (
"fmt"
"github.com/syntaqx/env"
)
func main() {
port := env.GetWithFallback("PORT", "8080")
fmt.Printf("Port: %s\n", port)
// 假设HOSTS的值是一个逗号分隔的字符串列表
// 例如: some-host:8000,another-host:8000
hosts, err := env.GetStringSliceWithFallback("HOSTS", []string{"fallback-host-1:8000", "fallback-host-2:8000"})
if err != nil {
fmt.Printf("Error getting hosts: %v\n", err)
} else {
fmt.Printf("Hosts: %v\n", hosts)
}
}
解组到结构体
Unmarshal
函数允许你基于结构体标签将环境变量加载到结构体中。你可以使用default
或fallback
作为回退值,使用required
来强制要求必须设置环境变量。
package main
import (
"fmt"
"log"
"github.com/syntaqx/env"
)
type DatabaseConfig struct {
Host string `env:"DATABASE_HOST,default=localhost"`
Port int `env:"DATABASE_PORT|DB_PORT,fallback=3306"`
Username string `env:"DATABASE_USERNAME,default=root"`
Password string `env:"DATABASE_PASSWORD,required"`
Database string `env:"DATABASE_NAME"`
}
type Config struct {
Debug bool `env:"DEBUG"`
Port string `env:"PORT,default=8080"`
Database DatabaseConfig
}
func main() {
var cfg Config
// 设置示例环境变量
_ = env.Set("DEBUG", "true")
_ = env.Set("PORT", "9090")
_ = env.Set("DATABASE_HOST", "dbhost")
_ = env.Set("DATABASE_PORT", "5432")
_ = env.Set("DATABASE_USERNAME", "admin")
_ = env.Set("DATABASE_PASSWORD", "secret")
_ = env.Set("DATABASE_NAME", "mydb")
if err := env.Unmarshal(&cfg); err != nil {
log.Fatalf("Error unmarshalling config: %v", err)
}
fmt.Printf("Config: %+v\n", cfg)
}
嵌套结构体前缀
你可以使用嵌套前缀来分组环境变量。这允许你在多个地方重用相同的结构体,而不必担心环境变量冲突。
package main
import (
"fmt"
"log"
"github.com/syntaqx/env"
)
type DatabaseConfig struct {
Host string `env:"HOST,default=localhost"`
Port int `env:"PORT,fallback=3306"`
Username string `env:"USERNAME,default=root"`
Password string `env:"PASSWORD,required"`
Database string `env:"NAME"`
}
type Config struct {
Debug bool `env:"DEBUG"`
Port string `env:"PORT,default=8080"`
ReadDatabase DatabaseConfig `env:"READ_DATABASE"`
WriteDatabase DatabaseConfig `env:"WRITE_DATABASE"`
}
func main() {
var cfg Config
// 设置示例环境变量
_ = env.Set("DEBUG", "true")
_ = env.Set("PORT", "9090")
_ = env.Set("READ_DATABASE_HOST", "read-dbhost")
_ = env.Set("READ_DATABASE_PORT", "5432")
_ = env.Set("READ_DATABASE_USERNAME", "read-admin")
_ = env.Set("READ_DATABASE_PASSWORD", "read-secret")
_ = env.Set("READ_DATABASE_NAME", "read-mydb")
_ = env.Set("WRITE_DATABASE_HOST", "write-dbhost")
_ = env.Set("WRITE_DATABASE_PORT", "5432")
_ = env.Set("WRITE_DATABASE_USERNAME", "write-admin")
_ = env.Set("WRITE_DATABASE_PASSWORD", "write-secret")
_ = env.Set("WRITE_DATABASE_NAME", "write-mydb")
if err := env.Unmarshal(&cfg); err != nil {
log.Fatalf("Error unmarshalling config: %v", err)
}
fmt.Printf("Config: %+v\n", cfg)
}
切片类型默认值
当使用切片类型时,如果你声明单个值作为默认值,可以像平常一样使用default
标签:
type Config struct {
Hosts []string `env:"HOSTS,default=localhost"`
}
但是如果你想声明多个值作为默认值,必须将值括在方括号中:
type Config struct {
Hosts []string `env:"HOSTS,default=[localhost,localhost2]"`
}
代码中的默认值
你也可以通过在代码中初始化结构体数据来定义默认值,然后再由env.Unmarshal
填充。但是,定义为结构体标签的默认值将优先于代码中定义的默认值。
type Config struct {
Username string `env:"USERNAME,default=admin"`
Password string `env:"PASSWORD"`
}
cfg := Config{
Username: "test",
Password: "password123",
}
if err := env.Unmarshal(&cfg); err != nil {
log.Fatalf("Error unmarshalling config: %v", err)
}
// { Username: "admin", Password: "password123" }
从文件读取
file
标签选项可用于指示变量的值应从文件中加载。文件的路径由变量的值给出。
echo "password123" > /run/secrets/password
type Config struct {
Username string `env:"USERNAME"`
Password string `env:"PASSWORD,file"`
}
cfg := Config{
Username: "test",
Password: "/run/secrets/password",
}
if err := env.Unmarshal(&cfg); err != nil {
log.Fatalf("Error unmarshalling config: %v", err)
}
// { "Username": "test", "Password": "password123" }
扩展变量
expand
标签选项可用于指示变量的值应在设置前扩展(以${var}
或$var
格式)。
type Config struct {
Username string `env:"USERNAME,expand"`
Password string `env:"PASSWORD,expand"`
}
这与default
标签选项配合使用效果很好:
type Config struct {
Address string `env:"ADDRESS,expand,default=${HOST}:${PORT}"`
}
此外,默认值可以从其他结构体字段引用。允许你在环境变量未设置时链接默认值,而不是回退到空值:
type Config struct {
Host string `env:"HOST,default=localhost"`
Port string `env:"PORT,default=8080"`
Address string `env:"ADDRESS,expand,default=${HOST}:${PORT}"`
}
贡献
欢迎提出问题或为项目做贡献。贡献总是受欢迎的!
许可证
本项目采用MIT许可证。
更多关于golang环境变量解析与结构体映射插件库env的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang环境变量解析与结构体映射插件库env的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang环境变量解析与结构体映射插件库env使用指南
env
是一个流行的Go语言库,用于将环境变量映射到结构体字段,简化配置管理。下面详细介绍其使用方法。
安装
go get github.com/caarlos0/env/v7
基本用法
简单示例
package main
import (
"fmt"
"log"
"github.com/caarlos0/env/v7"
)
type config struct {
Port int `env:"PORT" envDefault:"3000"`
LogLevel string `env:"LOG_LEVEL" envDefault:"info"`
Debug bool `env:"DEBUG" envDefault:"false"`
}
func main() {
cfg := config{}
if err := env.Parse(&cfg); err != nil {
log.Fatal(err)
}
fmt.Printf("Port: %d\n", cfg.Port)
fmt.Printf("LogLevel: %s\n", cfg.LogLevel)
fmt.Printf("Debug: %v\n", cfg.Debug)
}
支持的字段类型
env
支持多种数据类型:
- 基本类型:
string
,bool
,int
,int8
,int16
,int32
,int64
- 无符号整数:
uint
,uint8
,uint16
,uint32
,uint64
- 浮点数:
float32
,float64
- 时间类型:
time.Duration
,time.Time
- 切片:
[]string
,[]int
,[]float64
等 - 自定义类型(需实现
encoding.TextUnmarshaler
接口)
高级功能
嵌套结构体
type DatabaseConfig struct {
Host string `env:"DB_HOST" envDefault:"localhost"`
Port int `env:"DB_PORT" envDefault:"5432"`
Username string `env:"DB_USER" envDefault:"postgres"`
Password string `env:"DB_PASS" envDefault:""`
}
type AppConfig struct {
Port int `env:"PORT" envDefault:"8080"`
Database DatabaseConfig
Timeout time.Duration `env:"TIMEOUT" envDefault:"5s"`
}
func main() {
cfg := AppConfig{}
if err := env.Parse(&cfg); err != nil {
log.Fatal(err)
}
fmt.Printf("Database Host: %s\n", cfg.Database.Host)
}
切片类型
type config struct {
Hosts []string `env:"HOSTS" envSeparator:":"`
Ports []int `env:"PORTS" envSeparator:","`
}
func main() {
cfg := config{}
if err := env.Parse(&cfg); err != nil {
log.Fatal(err)
}
// 设置环境变量 HOSTS=host1:host2:host3
// 设置环境变量 PORTS=8080,8081,8082
fmt.Printf("Hosts: %v\n", cfg.Hosts)
fmt.Printf("Ports: %v\n", cfg.Ports)
}
自定义解析器
type URL struct {
Scheme string
Host string
Path string
}
func (u *URL) UnmarshalText(text []byte) error {
parsed, err := url.Parse(string(text))
if err != nil {
return err
}
u.Scheme = parsed.Scheme
u.Host = parsed.Host
u.Path = parsed.Path
return nil
}
type config struct {
APIEndpoint URL `env:"API_ENDPOINT" envDefault:"https://api.example.com/v1"`
}
func main() {
cfg := config{}
if err := env.Parse(&cfg); err != nil {
log.Fatal(err)
}
fmt.Printf("API Endpoint: %s://%s%s\n", cfg.APIEndpoint.Scheme, cfg.APIEndpoint.Host, cfg.APIEndpoint.Path)
}
必填字段验证
type config struct {
APIKey string `env:"API_KEY,required"`
Env string `env:"ENV" envDefault:"development"`
}
func main() {
cfg := config{}
if err := env.Parse(&cfg); err != nil {
log.Fatal(err) // 如果API_KEY未设置会报错
}
}
前缀处理
type config struct {
Host string `env:"HOST" envDefault:"localhost"`
Port int `env:"PORT" envDefault:"8080"`
}
func main() {
os.Setenv("APP_HOST", "example.com")
os.Setenv("APP_PORT", "3000")
cfg := config{}
opts := env.Options{Prefix: "APP_"}
if err := env.ParseWithOptions(&cfg, opts); err != nil {
log.Fatal(err)
}
fmt.Printf("Host: %s, Port: %d\n", cfg.Host, cfg.Port)
// 输出: Host: example.com, Port: 3000
}
最佳实践
- 集中管理配置:将所有配置放在一个结构体中,便于管理
- 提供默认值:为所有非必填字段提供合理的默认值
- 环境区分:使用前缀区分不同环境的配置
- 敏感信息:不要将密码等敏感信息硬编码,使用环境变量或配置中心
- 验证配置:在应用启动时验证关键配置项
完整示例
package main
import (
"fmt"
"log"
"net/url"
"os"
"time"
"github.com/caarlos0/env/v7"
)
type DatabaseConfig struct {
Host string `env:"DB_HOST" envDefault:"localhost"`
Port int `env:"DB_PORT" envDefault:"5432"`
Username string `env:"DB_USER" envDefault:"postgres"`
Password string `env:"DB_PASS,required"`
Name string `env:"DB_NAME" envDefault:"appdb"`
}
type RedisConfig struct {
Host string `env:"REDIS_HOST" envDefault:"localhost"`
Port int `env:"REDIS_PORT" envDefault:"6379"`
}
type AppConfig struct {
Env string `env:"ENV" envDefault:"development"`
Port int `env:"PORT" envDefault:"8080"`
Debug bool `env:"DEBUG" envDefault:"false"`
Timeout time.Duration `env:"TIMEOUT" envDefault:"30s"`
Database DatabaseConfig
Redis RedisConfig
AllowedIPs []string `env:"ALLOWED_IPS" envSeparator:"," envDefault:"127.0.0.1,::1"`
}
func main() {
// 模拟设置环境变量
os.Setenv("DB_PASS", "securepassword")
os.Setenv("ALLOWED_IPS", "192.168.1.1,192.168.1.2,10.0.0.1")
cfg := AppConfig{}
if err := env.Parse(&cfg); err != nil {
log.Fatalf("Failed to parse config: %v", err)
}
fmt.Printf("Environment: %s\n", cfg.Env)
fmt.Printf("Server Port: %d\n", cfg.Port)
fmt.Printf("Debug Mode: %v\n", cfg.Debug)
fmt.Printf("Timeout: %v\n", cfg.Timeout)
fmt.Printf("Database: %s@%s:%d/%s\n",
cfg.Database.Username,
cfg.Database.Host,
cfg.Database.Port,
cfg.Database.Name)
fmt.Printf("Redis: %s:%d\n", cfg.Redis.Host, cfg.Redis.Port)
fmt.Printf("Allowed IPs: %v\n", cfg.AllowedIPs)
}
env
库简化了Go应用程序的配置管理,通过结构体标签与环境变量映射,使配置更加清晰和类型安全。它支持丰富的特性,能满足大多数应用的配置需求。