Golang微服务配置工具 - Dotconfig的简单使用指南

Golang微服务配置工具 - Dotconfig的简单使用指南 这是我周六的一个项目。我主要是为了内部使用而构建它,因为我发现自己经常在多个项目中复制/粘贴类似的代码,但想着也许其他人也能从中获得一些用处:

GitHub - DeanPDX/dotconfig: Simplify configuration of microservices.

如今,我主要将我的 Go 代码部署到云提供商(Google Cloud、AWS 和 Azure),并通过密钥管理器暴露配置设置(我们不都是这样吗?)。有时我想在本地运行这些服务,并通过键/值对注入环境变量。这个包封装了读取键/值对的过程,并使用反射将环境变量转换为结构体:

package main

import  "github.com/DeanPDX/dotconfig"

// Our contrived AppConfig with env struct tags:
type AppConfig struct {
        MaxBytesPerRequest int     `env:"MAX_BYTES_PER_REQUEST"`
        APIVersion         float64 `env:"API_VERSION"`
        IsDev              bool    `env:"IS_DEV"`
        StripeSecret       string  `env:"STRIPE_SECRET"`
        WelcomeMessage     string  `env:"WELCOME_MESSAGE"`
}

func Main() {
        config, err := dotconfig.FromFileName[AppConfig](".env")
        // config is ready to use. Float/bool/int values will be 
        // correctly parsed. If you are developing locally you can
        // put an .env file in your working dir to supply the values.
        // In the cloud they should come from a secret manager.
}

我的目标是尽可能保持简单。用 env 标签定义你的结构体,这些标签将属性映射到环境变量。然后,它在本地开发(通过设置本地环境变量或在工作目录中包含一个 .env 文件)和在云端(通过密钥管理器提供环境变量)中就能“正常工作”。

以下是 .env 文件的预期格式:

MAX_BYTES_PER_REQUEST='1024'
API_VERSION='1.19'
# All of these are valie for booleans:
# 1, t, T, TRUE, true, True, 0, f, F, FALSE, false, False
IS_DEV='1'
STRIPE_SECRET='sk_test_insertkeyhere'
# Right now supporting newlines via "\n" in strings:
WELCOME_MESSAGE='Hello,\nWelcome to the app!\n-The App Dev Team'

解码逻辑大量借鉴了标准库中的 encoding/json。我还公开了一个名为 FromReader 的函数,以防你想从非文件源设置键/值对,或者想自己管理文件 IO。

如果你有任何问题,请随时提问。我也乐于接受反馈。再次强调——我希望尽可能保持简单,所以目前整个包的代码不到 200 行。更多信息和可运行的示例请参见 godoc


更多关于Golang微服务配置工具 - Dotconfig的简单使用指南的实战教程也可以访问 https://www.itying.com/category-94-b0.html

6 回复

我会看一下。谢谢,Karl!

更多关于Golang微服务配置工具 - Dotconfig的简单使用指南的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


我提交了一个GitHub拉取请求。主要的改动是关于单引号的处理,以及将单个错误改为使用错误集合。

如果你觉得可以,或许可以再稍微完善一下,然后我就可以在go4lage中使用它了 🙂

我在验证方面故意留有一些宽松的空间,部分原因是我设想了一种混合搭配的场景。例如,某些环境变量来自密钥管理器或其他来源,但您同时也有一个 .env 文件来覆盖某些选项。无论如何,我认为我们可以通过选项来实现您的“严格验证”场景和我的“宽松验证”场景。

嗯,我记不清当时具体是什么意思了。

首先,我认为 dotcofing 应该只是检查 .env 文件和结构体之间是否存在任何差异。也就是说,不能有缺失的字段,也不能有额外的字段,无论在哪一方。

它还应该收集信息/错误,并将其作为数组返回,这样如果存在两个错误,用户可以立即知道需要修改什么。

我想我下周可以帮忙处理这个问题(在此之前比较忙),并在 GitHub 上提一个请求。

看起来不错。你说得对,我也需要编写类似这样的代码,当然会更具体一些。

你确定单引号在 .env 文件中是常用的吗?

STRIPE_SECRET=‘sk_test_insertkeyhere’ 对比 STRIPE_SECRET=sk_test_insertkeyhere

你能让它同时适用于这两种情况吗?

应该在这里:

// Turn a line into key/value pair. Example line:
		// STRIPE_SECRET_KEY='sk_test_asDF!'
		key := line[0:strings.Index(line, "='")]
		value := line[len(key)+2:]
		// Trim closing single quote
		value = strings.TrimSuffix(value, "'")
		// Turn \n into newlines
		value = strings.ReplaceAll(value, `\n`, "\n")
		os.Setenv(key, value)

对于错误/信息,我需要以下内容:

  1. 如果 .env 文件中有未使用的行
  2. 如果需要的条目为空或缺失

(只是不在这里) STRIPE_SECRET= STRIPE_SECRET=‘’

  1. 如果有拼写错误或错误行

然后用户可以根据错误决定,如果这是必需的,他们是否在初始化时中止应用程序并强制用户输入特定字段。

这是一个很实用的配置管理工具,专门为Go微服务设计。Dotconfig通过结构体标签和环境变量的映射,简化了本地开发和云端部署的配置管理。下面是一个更完整的示例,展示如何在真实场景中使用:

package main

import (
    "fmt"
    "log"
    "github.com/DeanPDX/dotconfig"
)

// 定义微服务配置结构体
type ServiceConfig struct {
    Port        int      `env:"PORT"`
    DatabaseURL string   `env:"DATABASE_URL"`
    DebugMode   bool     `env:"DEBUG_MODE"`
    APIKeys     []string `env:"API_KEYS"`
    Timeout     float64  `env:"REQUEST_TIMEOUT"`
}

func main() {
    // 从.env文件加载配置
    config, err := dotconfig.FromFileName[ServiceConfig](".env")
    if err != nil {
        log.Fatalf("Failed to load config: %v", err)
    }
    
    // 使用配置
    fmt.Printf("Service starting on port %d\n", config.Port)
    fmt.Printf("Database URL: %s\n", config.DatabaseURL)
    fmt.Printf("Debug mode enabled: %v\n", config.DebugMode)
    
    // 启动服务
    startServer(config)
}

func startServer(cfg ServiceConfig) {
    // 使用配置启动服务
    // ...
}

对于云端部署,环境变量可以直接通过云平台设置:

// 在云环境中,直接使用环境变量
func init() {
    // 云环境会自动读取环境变量
    config, err := dotconfig.FromEnv[ServiceConfig]()
    if err != nil {
        log.Fatal(err)
    }
    // 使用配置初始化服务
}

Dotconfig支持的类型转换很实用,特别是布尔值和数组的解析:

type ComplexConfig struct {
    Enabled     bool      `env:"FEATURE_ENABLED"`
    RetryCount  int       `env:"RETRY_COUNT"`
    Hosts       []string  `env:"ALLOWED_HOSTS"`
    RateLimit   float64   `env:"RATE_LIMIT"`
}

// .env文件示例:
// FEATURE_ENABLED='true'
// RETRY_COUNT='3'
// ALLOWED_HOSTS='host1,host2,host3'
// RATE_LIMIT='100.5'

这个工具在保持简单性的同时,覆盖了微服务配置的主要使用场景。

回到顶部