golang环境变量解析到结构体插件库env的使用

Golang环境变量解析到结构体插件库env的使用

介绍

env是一个简单、零依赖的库,用于将环境变量解析到结构体中。

GoReleaser Logo

安装

go get github.com/caarlos0/env/v11

快速开始

基本用法

type config struct {
  Home string `env:"HOME"`
}

// 解析方式1
var cfg config
err := env.Parse(&cfg)

// 解析方式2(使用泛型)
cfg, err := env.ParseAs[config]()

完整示例

package main

import (
	"fmt"
	"time"
	
	"github.com/caarlos0/env/v11"
)

// 配置结构体
type Config struct {
	Home         string        `env:"HOME"`                           // 基本字符串类型
	Port         int           `env:"PORT" envDefault:"3000"`         // 带默认值的整型
	IsProduction bool          `env:"PRODUCTION"`                     // 布尔类型
	Hosts        []string      `env:"HOSTS" envSeparator:":"`         // 字符串切片,使用:分隔
	Duration     time.Duration `env:"DURATION"`                       // 时间间隔类型
	TempFolder   string        `env:"TEMP_FOLDER,expand"`             // 支持变量扩展
	RequiredVar  string        `env:"REQUIRED_VAR,required"`          // 必填字段
	SecretFile   string        `env:"SECRET_FILE,file"`                // 从文件读取内容
}

func main() {
	// 设置环境变量(实际使用时从系统环境变量获取)
	os.Setenv("HOME", "/tmp/home")
	os.Setenv("HOSTS", "host1:host2:host3")
	os.Setenv("DURATION", "1h30m")
	os.Setenv("TEMP_FOLDER", "$HOME/tmp")  // 使用变量扩展
	os.Setenv("REQUIRED_VAR", "must have")
	os.Setenv("SECRET_FILE", "./secret.txt")

	// 解析环境变量到结构体
	var cfg Config
	if err := env.Parse(&cfg); err != nil {
		fmt.Printf("Failed to parse env: %v\n", err)
		return
	}

	// 输出解析结果
	fmt.Printf("Home: %s\n", cfg.Home)
	fmt.Printf("Port: %d\n", cfg.Port)
	fmt.Printf("IsProduction: %t\n", cfg.IsProduction)
	fmt.Printf("Hosts: %v\n", cfg.Hosts)
	fmt.Printf("Duration: %v\n", cfg.Duration)
	fmt.Printf("TempFolder: %s\n", cfg.TempFolder)
	fmt.Printf("RequiredVar: %s\n", cfg.RequiredVar)
	fmt.Printf("SecretFile: %s\n", cfg.SecretFile)
}

主要功能

  • Parse: 将当前环境解析到指定类型
  • ParseAs: 使用泛型将当前环境解析到指定类型
  • ParseWithOptions: 使用自定义选项解析环境变量
  • ParseAsWithOptions: 使用自定义选项和泛型解析环境变量
  • Must: 可以包装Parse.*调用,在出错时panic
  • GetFieldParams: 获取类型的env解析选项
  • GetFieldParamsWithOptions: 使用自定义选项获取类型的env解析选项

支持的类型

env支持所有内置类型,以及一些常用类型:

  • 基本类型: bool, string, 各种整型和浮点型
  • 时间类型: time.Duration, time.Location
  • 其他: encoding.TextUnmarshaler, url.URL
  • 指针、切片和指针切片
  • 上述类型的映射(map)

标签说明

  • env: 设置环境变量名,并可接受下面描述的标签选项
  • envDefault: 设置字段的默认值
  • envPrefix: 可用于复杂类型字段,为其所有环境变量设置前缀
  • envSeparator: 设置切片和映射中项的分隔符(默认: ,)
  • envKeyValSeparator: 设置映射中键和值的分隔符(默认: :)

注意事项

未导出的字段会被env忽略,这是设计如此且不会改变。

高级选项

env标签支持以下选项:

  • ,expand: 扩展环境变量,例如FOO_${BAR}
  • ,file: 指示变量内容是应读取的文件路径
  • ,init: 初始化nil指针
  • ,notEmpty: 如果环境变量为空则报错
  • ,required: 如果环境变量未设置则报错
  • ,unset: 使用后取消设置环境变量

解析选项

对于以WithOptions结尾的函数,有以下选项可用:

  • Environment: 用于替代os.Environ()的键值对
  • TagName: 指定要使用的标签名而不是默认的env
  • PrefixTagName: 指定要使用的前缀标签名而不是默认的envPrefix
  • DefaultValueTagName: 指定要使用的默认值标签名而不是默认的envDefault
  • RequiredIfNoDef: 如果未声明envDefault,则将所有env字段设置为必需
  • OnSet: 允许挂钩到env解析并在设置值时执行某些操作
  • Prefix: 在所有环境变量中使用的前缀
  • UseFieldNameByDefault: 定义如果env键缺失时是否默认使用字段名
  • FuncMap: 自定义类型的解析函数

更多关于golang环境变量解析到结构体插件库env的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang环境变量解析到结构体插件库env的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang 环境变量解析到结构体 - env 库使用指南

在 Go 开发中,将环境变量解析到结构体是一种常见的配置管理方式。env 是一个流行的 Go 库,可以方便地将环境变量映射到结构体字段。下面我将详细介绍如何使用这个库。

安装 env 库

首先需要安装 env 库:

go get github.com/caarlos0/env/v7

基本用法

1. 定义配置结构体

package main

import (
	"fmt"
	"time"
	
	"github.com/caarlos0/env/v7"
)

type Config struct {
	Home         string        `env:"HOME"`
	Port         int           `env:"PORT" envDefault:"3000"`
	Password     string        `env:"PASSWORD,required"`
	IsProduction bool          `env:"PRODUCTION"`
	Hosts        []string      `env:"HOSTS" envSeparator:":"`
	Duration     time.Duration `env:"DURATION"`
	TempFolder   string        `env:"TEMP_FOLDER" envDefault:"${HOME}/tmp"`
}

2. 解析环境变量到结构体

func main() {
	cfg := Config{}
	if err := env.Parse(&cfg); err != nil {
		fmt.Printf("%+v\n", err)
	}
	
	fmt.Printf("%+v\n", cfg)
}

标签说明

  • env:"VAR_NAME" - 指定环境变量名
  • envDefault:"value" - 设置默认值
  • required - 标记该字段为必填
  • envSeparator:":" - 指定切片类型的分隔符
  • unset - 解析后从环境中删除该变量

高级用法

1. 自定义解析器

type CustomType struct {
	Value string
}

func (c *CustomType) UnmarshalText(text []byte) error {
	c.Value = string(text) + "-custom"
	return nil
}

type Config struct {
	Custom CustomType `env:"CUSTOM"`
}

func main() {
	os.Setenv("CUSTOM", "value")
	
	cfg := Config{}
	if err := env.Parse(&cfg); err != nil {
		panic(err)
	}
	
	fmt.Println(cfg.Custom.Value) // 输出: value-custom
}

2. 嵌套结构体

type NestedConfig struct {
	Foo string `env:"FOO"`
	Bar int    `env:"BAR"`
}

type Config struct {
	Nested NestedConfig `envPrefix:"NESTED_"`
}

func main() {
	os.Setenv("NESTED_FOO", "foo")
	os.Setenv("NESTED_BAR", "42")
	
	cfg := Config{}
	if err := env.Parse(&cfg); err != nil {
		panic(err)
	}
	
	fmt.Printf("%+v\n", cfg.Nested) // 输出: {Foo:foo Bar:42}
}

3. 环境变量扩展

type Config struct {
	Home       string `env:"HOME"`
	ConfigPath string `env:"CONFIG_PATH" envDefault:"${HOME}/.config/app"`
}

func main() {
	cfg := Config{}
	if err := env.Parse(&cfg); err != nil {
		panic(err)
	}
	
	fmt.Println(cfg.ConfigPath) // 输出类似: /home/user/.config/app
}

完整示例

package main

import (
	"fmt"
	"log"
	"os"
	"time"
	
	"github.com/caarlos0/env/v7"
)

type Config struct {
	AppName      string        `env:"APP_NAME" envDefault:"MyApp"`
	Debug        bool          `env:"DEBUG"`
	Port         int           `env:"PORT" envDefault:"8080"`
	Timeout      time.Duration `env:"TIMEOUT" envDefault:"30s"`
	DatabaseURL  string        `env:"DATABASE_URL,required"`
	AllowedHosts []string      `env:"ALLOWED_HOSTS" envSeparator:","`
	FeatureFlags struct {
		NewUI    bool `env:"FEATURE_NEW_UI"`
		DarkMode bool `env:"FEATURE_DARK_MODE" envDefault:"true"`
	} `envPrefix:"FEATURE_"`
}

func main() {
	// 设置一些环境变量(实际使用时从系统环境变量获取)
	os.Setenv("DATABASE_URL", "postgres://user:pass@localhost:5432/db")
	os.Setenv("ALLOWED_HOSTS", "localhost,127.0.0.1,example.com")
	os.Setenv("FEATURE_NEW_UI", "true")
	
	var cfg Config
	if err := env.Parse(&cfg); err != nil {
		log.Fatalf("Failed to parse config: %v", err)
	}
	
	fmt.Printf("Config: %+v\n", cfg)
	fmt.Printf("AppName: %s\n", cfg.AppName)
	fmt.Printf("Port: %d\n", cfg.Port)
	fmt.Printf("DatabaseURL: %s\n", cfg.DatabaseURL)
	fmt.Printf("AllowedHosts: %v\n", cfg.AllowedHosts)
	fmt.Printf("FeatureFlags - NewUI: %v, DarkMode: %v\n", 
		cfg.FeatureFlags.NewUI, cfg.FeatureFlags.DarkMode)
}

注意事项

  1. 结构体字段必须是可导出的(首字母大写)
  2. 对于必填字段(required),如果未设置会返回错误
  3. 默认值仅在环境变量未设置时使用
  4. 支持基本类型、切片、嵌套结构体和自定义类型

env 库提供了一种简洁、类型安全的方式来管理应用程序配置,特别适合12-factor应用开发。通过结构体标签,可以清晰地表达配置需求,使代码更易于维护和理解。

希望这个指南能帮助你有效地使用 env 库来管理 Go 应用程序的环境变量配置!

回到顶部