配置
介绍
Goyave 提供了一个灵活的结构化配置系统,支持文件配置同时也支持环境变量。框架的大部分核心都是可配置的。任何其他包也可以注册自己的配置条目。
要配置您的应用程序,请使用项目根目录下的 config.json
文件。如果配置文件缺少某些条目,将使用默认值。请参阅下面的配置参考以了解更多信息。
术语
条目:配置条目是使用键访问的值。键具有点分隔的格式。(例如:app.name
)
注册条目:通知框架期望具有给定键的条目。注册条目允许设置默认值,如果应用程序配置文件中未提供此条目,则使用默认值,强制执行此条目的某种类型(例如,如果需要是整数),并设置允许的值列表。
类别:类别在配置文件中由 JSON 对象表示,由大括号界定。子类别是不是根级别的类别。例如:server.proxy
是 server
类别的子类别。
加载配置
自动加载
默认情况下,在使用 goyave.New()
初始化服务器时自动加载配置。
大多数项目需要基于环境的不同配置值。例如,如果您在本地开发、在持续集成管道内的测试环境中或在生产环境中,您不会连接到同一个数据库。Goyave 支持多种配置。如果您使用 config.Load()
或自动加载器,框架将根据环境变量 GOYAVE_ENV
选择适当的文件。
GOYAVE_ENV | 配置文件 |
---|---|
test | config.test.json |
production | config.production.json |
custom_env | config.custom_env.json |
local / localhost / 未设置 | config.json |
如果您想使用相同的逻辑自己加载配置,可以使用 config.Load()
:
import (
"fmt"
"os"
"goyave.dev/goyave/v5/config"
"goyave.dev/goyave/v5/util/errors"
)
func main() {
cfg, err := config.Load()
if err != nil {
fmt.Fprintln(os.Stderr, err.(*errors.Error).String())
os.Exit(1)
}
opts := goyave.Options{
Config: cfg,
}
//...
}
从文件加载
您可以使用绝对路径或相对于工作目录的路径加载配置文件。
import (
"fmt"
"os"
"goyave.dev/goyave/v5/config"
"goyave.dev/goyave/v5/util/errors"
)
func main() {
cfg, err := config.LoadFrom("config.json")
if err != nil {
fmt.Fprintln(os.Stderr, err.(*errors.Error).String())
os.Exit(1)
}
opts := goyave.Options{
Config: cfg,
}
//...
}
从 JSON 或嵌入加载
您还可以选择从原始 JSON 字符串或 embed 加载配置。
import (
_ "embed"
"fmt"
"os"
"goyave.dev/goyave/v5/config"
"goyave.dev/goyave/v5/util/errors"
)
//go:embed config.json
var cfgJSON string
func main() {
cfg, err := config.LoadJSON(cfgJSON)
if err != nil {
fmt.Fprintln(os.Stderr, err.(*errors.Error).String())
os.Exit(1)
}
opts := goyave.Options{
Config: cfg,
}
//...
}
TIP
您可以使用构建约束为每个环境加载不同的配置文件。为每个环境创建一个 config_<env>.go
文件。
config_local.go
//go:build !production && !staging
package main
import _ "embed"
//go:embed config.json
var cfgJSON string
config_production.go
//go:build production
package main
import _ "embed"
//go:embed config.production.json
var cfgJSON string
然后使用构建标签:go run -tags production
或 go build -tags production
。
验证
所有条目都经过验证。这意味着如果您在配置中提供了无效值(例如,如果指定的端口不是数字),应用程序将不会启动。
每个条目都注册了默认值、类型和授权值。从 JSON 解析的原始值可能会转换为期望的类型(如果值允许)。例如,JSON 中解析的数字默认总是 float64
,但如果条目指定类型为 int
,配置加载器将尝试将数字转换为 int
。如果条目被指定为切片,它将被转换为期望类型的切片,而不是总是以 []any
结束。
环境变量
您可以在配置文件中使用环境变量。环境变量通过以下语法识别:${VARIABLE_NAME}
。
{
"database": {
"host": "${DB_HOST}"
}
}
注意:此语法是严格的。如果字符串不以 ${
开头或不以 }
结尾,则不会被视为环境变量。因此,不支持像 ${VAR_1}-${VAR_2}
这样的模板。
支持 string
、int
、float64
和 bool
值。如果配置条目期望是这些类型之一,环境变量的内容将自动转换,如上文验证部分所述。如果转换失败,将返回配置加载错误。
如果配置文件中提到的环境变量未设置,配置验证将不会通过。切片内部不支持环境变量。
使用配置
所有条目都可以使用点分隔路径访问。例如,如果您想访问 app 类别中的 name
条目,键将是 app.name
。您不能一次检索整个类别。
cfg.Get("app.name") // 类型 any
cfg.GetString("app.name")
cfg.GetBool("app.debug")
cfg.GetInt("server.port")
cfg.GetFloat("server.maxUploadSize")
cfg.GetStringSlice("path.to.slice")
cfg.GetBoolSlice("path.to.slice")
cfg.GetIntSlice("path.to.slice")
cfg.GetFloatSlice("path.to.slice")
cfg.Has("custom_entry") // 如果条目存在则返回 true
如果请求的条目不是 getter 期望的类型,函数将 panic。
请参阅参考。
配置参考
应用
条目 | 类型 | 默认值 | 说明 |
---|---|---|---|
app.name | string | "goyave" | |
app.environment | string | "localhost" | |
app.debug | bool | true | 激活时,使用人类可读的日志格式化器而不是 JSON 结构化日志,并在响应中发送错误详情。在生产环境中禁用此功能! |
app.defaultLanguage | string | "en-US" | 参见本地化部分 |
服务器
条目 | 类型 | 默认值 | 说明 |
---|---|---|---|
server.host | string | "127.0.0.1" | |
server.domain | string | "" | 用于 URL 生成。留空以使用 IP。 |
server.port | int | 8080 | 如果设置为 0 ,则自动选择端口号,可以通过 server.Port() 检索。所选端口不反映在配置中。 |
server.writeTimeout | int | 10 | *http.Server 的 WriteTimeout (秒) |
server.readTimeout | int | 10 | *http.Server 的 ReadTimeout (秒) |
server.readHeaderTimeout | int | 10 | *http.Server 的 ReadHeaderTimeout (秒) |
server.idleTimeout | int | 20 | *http.Server 的 IdleTimeout (秒) |
server.websocketCloseTimeout | int | 10 | WebSocket 关闭握手的最大时间(秒) |
server.maxUploadSize | float64 | 10 | 请求的最大大小,单位 MiB |
代理
此部分用于 URL 生成(server.ProxyBaseURL()
),如果您在反向代理(如 nginx 或 apache)后面运行应用程序。这些条目对网络没有影响,也不是必需的。
条目 | 类型 | 接受的值 | 默认值 | 说明 |
---|---|---|---|---|
server.proxy.protocol | string | "http" , "https" | "http" | |
server.proxy.host | string | 任意 | 代理的公共主机或域名 | |
server.proxy.port | int | 任意 | 80 | |
server.proxy.base | string | 任意 | "" | 基础路径(通常以 / 开头) |
数据库
条目 | 类型 | 默认值 | 说明 |
---|---|---|---|
database.connection | string | "none" | 参见数据库指南 |
database.host | string | "127.0.0.1" | |
database.port | int | 0 | |
database.name | string | "" | |
database.username | string | "" | |
database.password | string | "" | |
database.options | string | "" | 创建连接时传递给 DSN 的选项。 |
database.maxOpenConnections | int | 20 | |
database.maxIdleConnections | int | 20 | |
database.maxLifetime | int | 300 | 连接可重用的最长时间(秒)。 |
database.defaultReadQueryTimeout | int | 20000 | 读取查询的最大执行时间(毫秒) |
database.defaultWriteQueryTimeout | int | 40000 | 写入查询的最大执行时间(毫秒) |
Gorm 配置
条目 | 类型 | 默认值 |
---|---|---|
database.config.skipDefaultTransaction | bool | false |
database.config.dryRun | bool | false |
database.config.prepareStmt | bool | true |
database.config.disableNestedTransaction | bool | false |
database.config.allowGlobalUpdate | bool | false |
database.config.disableAutomaticPing | bool | false |
database.config.disableForeignKeyConstraintWhenMigrating | bool | false |
TIP
有关更多详细信息,请参阅 Gorm 的文档。
自定义配置条目
配置可以扩展。您开发的插件或包很可能使用某种形式的选项。这些选项可以添加到配置系统中,因此不需要在代码中设置或进行一些布线。
您可以使用 config.Register()
注册新的配置条目及其验证。
WARNING
未注册的配置条目仍然可以加载。但是,它们的类型将根据从配置文件解析的值自动确定。为了利用验证和转换系统,并确保您的自定义条目具有您期望的类型,您应始终使用 config.Register()
注册它们。
每个模块应在 init()
函数中注册其配置条目,即使它们没有默认值,以确保它们将被验证。 每个模块应使用自己的类别,并使用既表达性强又唯一的名称以避免冲突。 例如,auth
包注册了 auth.basic.username
和 auth.jwt.expiry
等,从而为其包创建一个类别,并为其功能创建两个子类别。
要注册没有默认值的条目(仅指定如何验证),将 Entry.Value
设置为 nil
。您可以将 Entry.Required
设置为 true
以防止 nil
值。
如果此键的条目已存在且与作为此函数参数传递的条目不完全相同,则会 panic。另一方面,如果条目相同,则不会发生冲突,因此配置保持当前状态。
import (
"reflect"
"goyave.dev/goyave/v5/config"
)
func init() {
config.Register("customCategory.customEntry", config.Entry{
Value: "默认值",
Type: reflect.String,
IsSlice: false,
AuthorizedValues: []any{},
Required: true,
})
}