Skip to content
鼓励作者:欢迎打赏犒劳

环境变量

go项目获取环境变量的方式有以下几种。

  1. 命令行启动的时候指定
  2. 通过项目的配置文件.env
  3. 通过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)

如有转载或 CV 的请标注本站原文地址