Skip to content

配置

介绍

Goyave 提供了一个灵活的结构化配置系统,支持文件配置同时也支持环境变量。框架的大部分核心都是可配置的。任何其他包也可以注册自己的配置条目。

要配置您的应用程序,请使用项目根目录下的 config.json 文件。如果配置文件缺少某些条目,将使用默认值。请参阅下面的配置参考以了解更多信息。

WARNING

配置可以在运行时临时更改,但该操作不是并发安全的。因此建议不要在测试之外使用 Config.Set()

在运行时更改配置是一个罕见的用例,因此决定不需要同步以获得更好的性能。

术语

条目:配置条目是使用键访问的值。键具有点分隔的格式。(例如:app.name

注册条目:通知框架期望具有给定键的条目。注册条目允许设置默认值,如果应用程序配置文件中未提供此条目,则使用默认值,强制执行此条目的某种类型(例如,如果需要是整数),并设置允许的值列表。

类别:类别在配置文件中由 JSON 对象表示,由大括号界定。子类别是不是根级别的类别。例如:server.proxyserver 类别的子类别。

加载配置

自动加载

默认情况下,在使用 goyave.New() 初始化服务器时自动加载配置。

大多数项目需要基于环境的不同配置值。例如,如果您在本地开发、在持续集成管道内的测试环境中或在生产环境中,您不会连接到同一个数据库。Goyave 支持多种配置。如果您使用 config.Load() 或自动加载器,框架将根据环境变量 GOYAVE_ENV 选择适当的文件。

GOYAVE_ENV配置文件
testconfig.test.json
productionconfig.production.json
custom_envconfig.custom_env.json
local / localhost / 未设置config.json

如果您想使用相同的逻辑自己加载配置,可以使用 config.Load()

go
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,
	}

	//...
}

从文件加载

您可以使用绝对路径或相对于工作目录的路径加载配置文件。

go
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 加载配置。

go
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
//go:build !production && !staging

package main

import _ "embed"

//go:embed config.json
var cfgJSON string

config_production.go

go
//go:build production

package main

import _ "embed"

//go:embed config.production.json
var cfgJSON string

然后使用构建标签:go run -tags productiongo build -tags production

验证

所有条目都经过验证。这意味着如果您在配置中提供了无效值(例如,如果指定的端口不是数字),应用程序将不会启动。

每个条目都注册了默认值、类型和授权值。从 JSON 解析的原始值可能会转换为期望的类型(如果值允许)。例如,JSON 中解析的数字默认总是 float64,但如果条目指定类型为 int,配置加载器将尝试将数字转换为 int。如果条目被指定为切片,它将被转换为期望类型的切片,而不是总是以 []any 结束。

环境变量

您可以在配置文件中使用环境变量。环境变量通过以下语法识别:${VARIABLE_NAME}

json
{
  "database": {
    "host": "${DB_HOST}"
  }
}

注意此语法是严格的。如果字符串不以 ${ 开头或不以 } 结尾,则不会被视为环境变量。因此,不支持${VAR_1}-${VAR_2} 这样的模板。

支持 stringintfloat64bool 值。如果配置条目期望是这些类型之一,环境变量的内容将自动转换,如上文验证部分所述。如果转换失败,将返回配置加载错误。

如果配置文件中提到的环境变量未设置,配置验证将不会通过。切片内部不支持环境变量。

使用配置

所有条目都可以使用点分隔路径访问。例如,如果您想访问 app 类别中的 name 条目,键将是 app.name。您不能一次检索整个类别。

go
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.namestring"goyave"
app.environmentstring"localhost"
app.debugbooltrue激活时,使用人类可读的日志格式化器而不是 JSON 结构化日志,并在响应中发送错误详情。在生产环境中禁用此功能!
app.defaultLanguagestring"en-US"参见本地化部分

服务器

条目类型默认值说明
server.hoststring"127.0.0.1"
server.domainstring""用于 URL 生成。留空以使用 IP。
server.portint8080如果设置为 0,则自动选择端口号,可以通过 server.Port() 检索。所选端口反映在配置中。
server.writeTimeoutint10*http.ServerWriteTimeout(秒)
server.readTimeoutint10*http.ServerReadTimeout(秒)
server.readHeaderTimeoutint10*http.ServerReadHeaderTimeout(秒)
server.idleTimeoutint20*http.ServerIdleTimeout(秒)
server.websocketCloseTimeoutint10WebSocket 关闭握手的最大时间(秒)
server.maxUploadSizefloat6410请求的最大大小,单位 MiB

代理

此部分用于 URL 生成(server.ProxyBaseURL()),如果您在反向代理(如 nginx 或 apache)后面运行应用程序。这些条目对网络没有影响,也不是必需的。

条目类型接受的值默认值说明
server.proxy.protocolstring"http", "https""http"
server.proxy.hoststring任意代理的公共主机或域名
server.proxy.portint任意80
server.proxy.basestring任意""基础路径(通常以 / 开头)

数据库

条目类型默认值说明
database.connectionstring"none"参见数据库指南
database.hoststring"127.0.0.1"
database.portint0
database.namestring""
database.usernamestring""
database.passwordstring""
database.optionsstring""创建连接时传递给 DSN 的选项。
database.maxOpenConnectionsint20
database.maxIdleConnectionsint20
database.maxLifetimeint300连接可重用的最长时间(秒)。
database.defaultReadQueryTimeoutint20000读取查询的最大执行时间(毫秒)
database.defaultWriteQueryTimeoutint40000写入查询的最大执行时间(毫秒)

Gorm 配置

条目类型默认值
database.config.skipDefaultTransactionboolfalse
database.config.dryRunboolfalse
database.config.prepareStmtbooltrue
database.config.disableNestedTransactionboolfalse
database.config.allowGlobalUpdateboolfalse
database.config.disableAutomaticPingboolfalse
database.config.disableForeignKeyConstraintWhenMigratingboolfalse

TIP

有关更多详细信息,请参阅 Gorm 的文档

自定义配置条目

配置可以扩展。您开发的插件或包很可能使用某种形式的选项。这些选项可以添加到配置系统中,因此不需要在代码中设置或进行一些布线。

您可以使用 config.Register() 注册新的配置条目及其验证。

WARNING

未注册的配置条目仍然可以加载。但是,它们的类型将根据从配置文件解析的值自动确定。为了利用验证和转换系统,并确保您的自定义条目具有您期望的类型,您应始终使用 config.Register() 注册它们

每个模块应在 init() 函数中注册其配置条目,即使它们没有默认值,以确保它们将被验证。 每个模块应使用自己的类别,并使用既表达性强又唯一的名称以避免冲突。 例如,auth 包注册了 auth.basic.usernameauth.jwt.expiry 等,从而为其包创建一个类别,并为其功能创建两个子类别。

要注册没有默认值的条目(仅指定如何验证),将 Entry.Value 设置为 nil。您可以将 Entry.Required 设置为 true 以防止 nil 值。

如果此键的条目已存在且与作为此函数参数传递的条目不完全相同,则会 panic。另一方面,如果条目相同,则不会发生冲突,因此配置保持当前状态。

go
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,
	})
}