
环境变量
go项目获取环境变量的方式有以下几种。
- 命令行启动的时候指定
- 通过项目的配置文件
.env
- 通过docker文件,其实也属于命令行指定,不过是将很多命令打包了
启动的时候指定变量
shell
# Linux/Mac
export ENV=production
go run main.go
# 或者一行命令
ENV=production go run main.go
# Windows
set ENV=production
go run main.go
使用 .env 文件
默认是加载的.env
文件,不过可以通过环境变量+配置文件的方式来实现不同的环境配置
.env
text
# .env 文件
ENV=development
DB_HOST=localhost
DB_PORT=3306
DB_USER=root
DB_PASS=password
加载文件
go
// 使用 github.com/joho/godotenv 包
package main
import (
"log"
"os"
"github.com/joho/godotenv"
)
func main() {
// 加载 .env 文件
err := godotenv.Load()
if err != nil {
log.Fatal("Error loading .env file")
}
env := os.Getenv("ENV")
dbHost := os.Getenv("DB_HOST")
log.Printf("Environment: %s, DB Host: %s", env, dbHost)
}
使用配置结构体
go
package config
import (
"os"
"strconv"
"github.com/joho/godotenv"
)
type Config struct {
Env string
DBHost string
DBPort int
DBUser string
DBPassword string
Debug bool
}
func Load() *Config {
// 加载 .env 文件(如果存在)
godotenv.Load()
return &Config{
Env: getEnv("ENV", "development"),
DBHost: getEnv("DB_HOST", "localhost"),
DBPort: getEnvAsInt("DB_PORT", 3306),
DBUser: getEnv("DB_USER", "root"),
DBPassword: getEnv("DB_PASSWORD", ""),
Debug: getEnvAsBool("DEBUG", true),
}
}
func getEnv(key, defaultValue string) string {
if value := os.Getenv(key); value != "" {
return value
}
return defaultValue
}
func getEnvAsInt(key string, defaultValue int) int {
if value := os.Getenv(key); value != "" {
if intValue, err := strconv.Atoi(value); err == nil {
return intValue
}
}
return defaultValue
}
func getEnvAsBool(key string, defaultValue bool) bool {
if value := os.Getenv(key); value != "" {
if boolValue, err := strconv.ParseBool(value); err == nil {
return boolValue
}
}
return defaultValue
}
Docker 环境
shell
FROM golang:1.19
WORKDIR /app
COPY . .
RUN go build -o main .
# 设置环境变量
ENV ENV=production
ENV DB_HOST=mysql-service
CMD ["./main"]
不同环境的配置文件
多环境配置
shell
# .env.development
ENV=development
DB_HOST=localhost
DEBUG=true
# .env.production
ENV=production
DB_HOST=mysql.prod.com
DEBUG=false
# .env.staging
ENV=staging
DB_HOST=mysql.staging.com
DEBUG=true
依赖系统或容器启动时设置的环境变量(如 APP_ENV=production)来决定加载哪个配置文件
go
package main
import (
"log"
"os"
"github.com/joho/godotenv"
)
func main() {
// 1. 先从环境变量获取当前环境,默认为开发环境
env := os.Getenv("APP_ENV")
if env == "" {
env = "development"
}
// 2. 根据环境变量拼接出对应的配置文件名称
envFile := ".env." + env
// 3. 尝试加载指定环境的配置文件,如果文件不存在则记录日志(可选)
// 你也可以使用 godotenv.Load(envFile) 强制要求文件必须存在
if err := godotenv.Load(envFile); err != nil {
log.Printf("Warning: Could not load %s file, using default environment variables\n", envFile)
}
// 4. 现在,你可以通过 os.Getenv 读取配置了
databaseUrl := os.Getenv("DATABASE_URL")
logLevel := os.Getenv("LOG_LEVEL")
// ... 使用配置初始化你的应用
}
实际运用
因为如果你要是指定了.env.production文件之后,就不会再默认加载env文件了,但是一般情况下,通常要加载env和特定环境的.env.production文件的。 一个存公共配置,一个是特殊配置。我们可以一块加载。
- 文件按照参数顺序依次加载
- 后加载文件中的同名环境变量会覆盖先加载文件中的值
在实际项目中管理多个环境(如开发、预发布、生产)时,一个常见的做法是
- 创建一个基础的 .env 文件,存放所有环境的共享配置或默认值。
- 为每个环境创建特定的环境文件,如 .env.development、.env.staging、.env.production,存放该环境特有的配置或需要覆盖的共享配置。
- 在代码中,根据当前环境(通常由一个如 APP_ENV 这样的环境变量决定)来决定加载哪些文件
go
env := os.Getenv("APP_ENV")
if env == "" {
env = "development"
}
// 加载顺序:先通用配置(.env),后特定环境配置,后者覆盖前者
godotenv.Load(".env", ".env."+env)