跳转至正文

Config 使用说明 ​

github.com/prismgo/framework/config 提供 Laravel 风格的运行时配置仓库:配置文件通过 Add 注册为命名空间,.env 和系统环境变量通过 Env 读取,业务代码再用点路径读取配置值。

业务代码通常直接导入 github.com/prismgo/framework/config,并在应用的 config/*.go 中注册自己的配置命名空间。

快速开始 ​

定义一个配置命名空间:

go
package config

func init() {
	Add("mail", func() map[string]interface{} {
		return map[string]interface{}{
			"host": Env("MAIL_HOST", "127.0.0.1"),
			"port": Env("MAIL_PORT", 1025),
			"from": map[string]interface{}{
				"address": Env("MAIL_FROM_ADDRESS", "noreply@example.com"),
				"name":    Env("MAIL_FROM_NAME", "prismgo"),
			},
		}
	})
}

读取配置:

go
package service

import (
	"strconv"

	"github.com/prismgo/framework/config"
)

func mailEndpoint() string {
	host := config.GetString("mail.host", "127.0.0.1")
	port := config.GetInt("mail.port", 1025)
	return host + ":" + strconv.Itoa(port)
}

本地 .env 示例:

dotenv
MAIL_HOST=smtp.example.com
MAIL_PORT=587
MAIL_FROM_ADDRESS=notice@example.com

组件用途 ​

github.com/prismgo/framework/config 主要解决四类问题:

能力用途
配置注册用 Add(name, fn) 注册 app、database、cache 等配置命名空间
环境变量读取用 Env 在注册函数里读取 .env 或系统环境变量
运行时读取用 GetString("app.name") 这类点路径读取嵌套配置
facade 管理用 Resolve 接入应用容器懒加载,测试通过容器显式绑定配置实例

配置仓库只负责“加载静态运行时配置”。租户后台可变配置、系统参数表等业务数据不应该放进这个包。

加载流程 ​

当前应用启动时,github.com/prismgo/framework/foundation 会注册配置工厂:

text
main.go
  -> bootstrap.NewApplication()
  -> foundation.NewApplication()
  -> registerConfigResource()
  -> 首次 config.Resolve / config.GetString
  -> 读取 .env,执行所有 Add 注册函数,生成运行时仓库

配置函数是在构建仓库时执行的,不是在包初始化时立即读取最终值。因此 config/*.go 中推荐只写声明式结构:

go
Add("app", func() map[string]interface{} {
	return map[string]interface{}{
		"name":  Env("APP_NAME", "prismgo"),
		"debug": Env("APP_DEBUG", false),
	}
})

.env 文件不存在时不会报错,会继续使用系统环境变量和默认值。.env 与系统环境变量同时存在时,显式提供的值会覆盖默认值。

环境变量函数 ​

Env ​

读取单个环境变量,缺失或空白时返回默认值:

go
debug := config.Env("APP_DEBUG", false)
name := config.Env("APP_NAME", "prismgo")

返回值会尽量按默认值类型转换。默认值是 bool、int、int64、uint、float64、string 时会得到对应类型。

配置注册 ​

Add(name, fn) 把一个命名空间注册到全局配置注册表。命名空间会成为点路径的第一段:

go
config.Add("audit", func() map[string]interface{} {
	return map[string]interface{}{
		"enabled": config.Env("AUDIT_ENABLED", true),
		"rules": map[string]interface{}{
			"prismgo": config.Env("AUDIT_PRISMGO", true),
		},
	}
})

读取时:

go
enabled := config.GetBool("audit.enabled", true)
prismgo := config.GetBool("audit.rules.prismgo", true)

注册函数返回的嵌套 map 会被整理成 map[string]any,因此 map[string]interface{} 和 map[string]any 都可以用。

配置读取 ​

常用读取函数:

函数返回类型用途
Get / GetStringstring字符串配置
GetIntint端口、数量、秒数等
GetInt64int64长整型配置
GetUintuint无符号整数配置
GetFloat64float64浮点配置
GetBoolbool开关配置
GetStringMapmap[string]any读取嵌套配置块
GetStringMapStringmap[string]string读取字符串映射

缺失配置可以传默认值:

go
appName := config.GetString("app.name", "prismgo")
debug := config.GetBool("app.debug", false)
timeout := config.GetInt("app.server.timeout", 15)

读取嵌套配置:

go
server := config.GetStringMap("app.server")
channels := config.GetStringMap("logging.channels")
labels := config.GetStringMapString("map.labels")

如果路径不存在,map 读取函数返回空 map,不返回 nil。

应用配置参考 ​

新项目的应用级配置位于 config/app.go,通过 config.Add("app", ...) 注册。.env 中的 APP_* 和 SERVER_* 会覆盖默认值。

基础应用配置 ​

配置路径环境变量默认值说明
app.nameAPP_NAMEPrismgo应用名称,用于框架需要展示或引用应用名的场景
app.envAPP_ENVproduction当前运行环境;迁移等高风险命令会用它判断是否需要 --force
app.keyAPP_KEY""应用加密密钥,见 加密
app.debugAPP_DEBUGfalse调试模式;生产环境必须为 false
app.urlAPP_URLhttp://localhost:8080命令行或非 HTTP 场景生成绝对 URL 时使用
app.timezoneAPP_TIMEZONEUTC应用时区配置
app.localeAPP_LOCALEen翻译组件默认语言
app.fallback_localeAPP_FALLBACK_LOCALEen当前语言缺少翻译时的 fallback
app.cipherAPP_CIPHERAES-256-GCM加密算法,当前支持 AES-256-GCM
app.previous_keysAPP_PREVIOUS_KEYS""逗号分隔的旧应用密钥,用于密钥轮换

HTTP Server 配置 ​

配置路径环境变量默认值说明
app.server.hostSERVER_HOST""监听主机
app.server.portSERVER_PORT8080监听端口
app.server.timeoutSERVER_TIMEOUT15兼容型请求超时 fallback
app.server.read_timeoutSERVER_READ_TIMEOUT15s读取完整请求超时
app.server.read_header_timeoutSERVER_READ_HEADER_TIMEOUT5s读取请求头超时
app.server.write_timeoutSERVER_WRITE_TIMEOUT30s写响应超时
app.server.idle_timeoutSERVER_IDLE_TIMEOUT60skeep-alive 空闲超时
app.server.shutdown_timeoutSERVER_SHUTDOWN_TIMEOUT15s优雅关闭等待时间
app.server.max_header_bytesSERVER_MAX_HEADER_BYTES1048576最大请求头字节数
app.server.max_multipart_memorySERVER_MAX_MULTIPART_MEMORY33554432multipart 表单内存上限
app.server.trusted_proxiesSERVER_TRUSTED_PROXIES""逗号分隔的可信代理
app.server.client_ip_headersSERVER_CLIENT_IP_HEADERSX-Forwarded-For,X-Real-IP解析客户端 IP 的请求头
app.server.access_logSERVER_ACCESS_LOGtrue是否启用访问日志
app.server.exception_handlerSERVER_EXCEPTION_HANDLERtrue是否挂载统一异常处理中间件

更多 HTTP 服务说明见 HTTP Server。

独立实例 ​

除了全局 facade,也可以创建独立 Config 实例。测试、脚本、临时工具中推荐使用独立实例,避免污染全局配置:

go
cfg, err := config.NewFromFile("testdata/.env")
if err != nil {
	return err
}

name := cfg.GetString("app.name", "prismgo")
debug := cfg.GetBool("app.debug", false)

复制一份当前配置:

go
clone := config.Clone()

Clone 返回独立仓库,后续 Reload 不会互相影响。

facade 入口 ​

github.com/prismgo/framework/config 的全局默认配置由 github.com/prismgo/framework/facade 托管。

函数用途
Resolve()从当前 Application 容器解析配置仓库
Clone()复制当前配置仓库,返回隔离副本
Reload()从默认 .env 重载当前配置对象
Empty()判断当前配置仓库是否为空

测试中常见写法:

go
func TestWithConfig(t *testing.T) {
	cfg, err := config.NewFromFile("testdata/.env")
	if err != nil {
		t.Fatal(err)
	}
	bindConfigForTest(t, cfg)

	got := config.GetString("app.name", "")
	if got == "" {
		t.Fatal("missing app name")
	}
}

使用建议 ​

  • 业务代码优先导入 github.com/prismgo/framework/config,不要在业务层直接重复封装环境变量读取。
  • 配置命名空间使用小写英文名,例如 app、database、wechat。
  • 新配置项应放进 config/*.go,不要在 service 中直接 os.Getenv。
  • 环境变量命名固定为一套当前名称,不为未上线阶段的旧变量名新增兼容入口。
  • 配置值缺失时要给出合理默认值,尤其是端口、超时、开关类配置。
  • 可变业务配置应放入业务表或专用 repository,不要塞进运行时配置仓库。