在实际开发中,我们常常需要根据不同环境(开发、测试、生产)来配置数据库地址、端口号、API 密钥等信息。环境变量(Environment Variables)是最常见、最安全的一种配置方式。

本文将从两个方面介绍如何在 Go 项目中使用环境变量:

  1. 使用标准库(不依赖任何第三方库)
  2. 使用 viper

1、使用 Go 标准库读取环境变量(推荐方式)

Go 提供了 os 包来处理环境变量,无需引入任何第三方依赖,非常适合对依赖敏感的项目。

1.1 os.Getenv() 读取变量

package main

import (
    "fmt"
    "os"
)

func main() {
    port := os.Getenv("PORT")
    if port == "" {
        port = "8080" // 设置默认值
    }

    fmt.Println("PORT:", port)
}

1.2 os.LookupEnv() 更安全的读取方式

if value, exists := os.LookupEnv("DB_HOST"); exists {
    fmt.Println("DB_HOST:", value)
} else {
    fmt.Println("DB_HOST is not set")
}

1.3 os.Setenv() 设置环境变量(仅对当前进程有效)

os.Setenv("PORT", "3000")

注意:这个设置只在当前 Go 程序运行期间有效,不会影响系统或其他进程。

2、手动解析 .env 文件(无第三方库)

虽然 Go 没有内建对 .env 文件的支持,我们可以手动读取 .env 文件并使用 os.Setenv() 进行配置:

示例代码:

package main

import (
    "bufio"
    "fmt"
    "os"
    "strings"
)

func loadEnvFile(filename string) error {
    file, err := os.Open(filename)
    if err != nil {
        return err
    }
    defer file.Close()

    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
        line := scanner.Text()
        if strings.HasPrefix(line, "#") || strings.TrimSpace(line) == "" {
            continue
        }

        parts := strings.SplitN(line, "=", 2)
        if len(parts) != 2 {
            continue
        }

        key := strings.TrimSpace(parts[0])
        value := strings.TrimSpace(parts[1])
        os.Setenv(key, value)
    }

    return scanner.Err()
}

func main() {
    err := loadEnvFile(".env")
    if err != nil {
        fmt.Println("Failed to load .env:", err)
    }

    fmt.Println("DB_HOST:", os.Getenv("DB_HOST"))
}

示例 .env 文件:

DB_HOST=localhost
DB_USER=root

3、使用 viper 读取环境变量(支持系统和 .env

viper 是 Go 中功能最强大的配置库之一。它支持多种格式(JSON、TOML、YAML、env)以及多种配置源(文件、环境变量、远程配置等)。

3.1 从系统环境变量读取

import (
    "fmt"
    "github.com/spf13/viper"
)

func main() {
    viper.SetDefault("PORT", "8080")
    viper.BindEnv("PORT")

    fmt.Println("PORT:", viper.GetString("PORT"))
}

如果你在 bash 中设置了 export PORT=3000,程序将读取到它。

3.2 自动绑定所有环境变量

viper.AutomaticEnv()

这样可以自动获取所有环境变量,无需显式调用 BindEnv

3.3 配合 .env 文件(需 godotenv 库)

虽然 viper 不直接支持 .env 文件,但可以配合 github.com/joho/godotenv 使用:

import (
    "fmt"
    "github.com/joho/godotenv"
    "github.com/spf13/viper"
    "log"
)

func main() {
    err := godotenv.Load(".env")
    if err != nil {
        log.Fatal("Error loading .env file")
    }

    viper.BindEnv("DB_HOST")
    viper.BindEnv("DB_USER")

    fmt.Println("DB_HOST:", viper.GetString("DB_HOST"))
    fmt.Println("DB_USER:", viper.GetString("DB_USER"))
}

4、总结对比

场景 推荐方法 是否依赖第三方
系统环境变量读取 os.Getenv() / viper.BindEnv 否 / 是
加载 .env 文件 手动解析 / godotenv + viper 否 / 是
自动绑定所有变量 viper.AutomaticEnv()
复杂配置文件(YAML等) viper

孟斯特

声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处。
Author: mengbin
blog: mengbin
Github: mengbin92
腾讯云开发者社区:孟斯特