Selaa lähdekoodia

Release v0.1.1220

qdy 2 kuukautta sitten
commit
bf99230c9b
3 muutettua tiedostoa jossa 344 lisäystä ja 69 poistoa
  1. 15
    5
      bootstraps/bootstrap.go
  2. 107
    49
      config/config.go
  3. 222
    15
      config/subconfigs/database_config.go

+ 15
- 5
bootstraps/bootstrap.go Näytä tiedosto

14
 	"git.x2erp.com/qdy/go-base/logger"
14
 	"git.x2erp.com/qdy/go-base/logger"
15
 )
15
 )
16
 
16
 
17
+// 定义接口
18
+type ShutdownHandler interface {
19
+	OnShutdown()
20
+}
21
+
17
 // Bootstrapper 服务启动器
22
 // Bootstrapper 服务启动器
18
 type Bootstrapper struct {
23
 type Bootstrapper struct {
19
 	serviceName    string
24
 	serviceName    string
81
 }
86
 }
82
 
87
 
83
 // Run 运行服务
88
 // Run 运行服务
84
-func (b *Bootstrapper) Run() {
89
+func (b *Bootstrapper) Run(handler ShutdownHandler) {
85
 	log.Printf("服务 %s 开始运行...", b.serviceName)
90
 	log.Printf("服务 %s 开始运行...", b.serviceName)
86
 
91
 
87
 	// 设置信号监听 - 在这里设置,而不是在New中
92
 	// 设置信号监听 - 在这里设置,而不是在New中
96
 	}()
101
 	}()
97
 
102
 
98
 	// 等待中断信号
103
 	// 等待中断信号
99
-	b.waitForShutdown()
104
+	b.waitForShutdown(handler)
100
 }
105
 }
101
 
106
 
102
 // RunTLS 运行HTTPS服务
107
 // RunTLS 运行HTTPS服务
103
-func (b *Bootstrapper) RunTLS(certFile, keyFile string) {
108
+func (b *Bootstrapper) RunTLS(certFile, keyFile string, handler ShutdownHandler) {
104
 	log.Printf("服务 %s 开始运行(HTTPS)...", b.serviceName)
109
 	log.Printf("服务 %s 开始运行(HTTPS)...", b.serviceName)
105
 
110
 
106
 	// 设置信号监听
111
 	// 设置信号监听
115
 	}()
120
 	}()
116
 
121
 
117
 	// 等待中断信号
122
 	// 等待中断信号
118
-	b.waitForShutdown()
123
+	b.waitForShutdown(handler)
119
 }
124
 }
120
 
125
 
121
 // waitForShutdown 等待关闭信号
126
 // waitForShutdown 等待关闭信号
122
-func (b *Bootstrapper) waitForShutdown() {
127
+func (b *Bootstrapper) waitForShutdown(handler ShutdownHandler) {
123
 	log.Println("按 Ctrl+C 停止服务")
128
 	log.Println("按 Ctrl+C 停止服务")
124
 
129
 
125
 	// 等待信号
130
 	// 等待信号
137
 		log.Println("HTTP服务器已关闭")
142
 		log.Println("HTTP服务器已关闭")
138
 	}
143
 	}
139
 
144
 
145
+	// 执行关闭处理
146
+	if handler != nil {
147
+		handler.OnShutdown()
148
+	}
149
+
140
 	// 停止日志写入
150
 	// 停止日志写入
141
 	logger.StopESWriter()
151
 	logger.StopESWriter()
142
 	log.Println("服务优雅关闭完成")
152
 	log.Println("服务优雅关闭完成")

+ 107
- 49
config/config.go Näytä tiedosto

4
 	"sync"
4
 	"sync"
5
 
5
 
6
 	"git.x2erp.com/qdy/go-base/config/subconfigs"
6
 	"git.x2erp.com/qdy/go-base/config/subconfigs"
7
+	"git.x2erp.com/qdy/go-base/logger"
7
 )
8
 )
8
 
9
 
9
-// IConfig 主配置接口
10
+// IConfig 主配置接口(更新支持多数据库)
10
 type IConfig interface {
11
 type IConfig interface {
11
-	GetDatabase() *subconfigs.DatabaseConfig
12
+	// 多数据库支持
13
+	GetDatabase() *subconfigs.DatabaseConfig                  // 获取默认数据库(向后兼容)
14
+	GetDatabases() *subconfigs.DatabasesConfig                // 获取所有数据库配置
15
+	GetDatabaseConfig(name string) *subconfigs.DatabaseConfig // 按名称获取数据库配置
16
+
17
+	// 其他配置(保持不变)
12
 	GetRedis() *subconfigs.RedisConfig
18
 	GetRedis() *subconfigs.RedisConfig
13
 	GetDoris() *subconfigs.DorisConfig
19
 	GetDoris() *subconfigs.DorisConfig
14
 	GetRabbitMQ() *subconfigs.RabbitMQConfig
20
 	GetRabbitMQ() *subconfigs.RabbitMQConfig
18
 	GetMicro() *subconfigs.MicroConfig
24
 	GetMicro() *subconfigs.MicroConfig
19
 	GetLog() *subconfigs.LogConfig
25
 	GetLog() *subconfigs.LogConfig
20
 	GetInitError() error
26
 	GetInitError() error
27
+
28
+	// 配置检查(更新)
21
 	IsDatabaseConfigured() bool
29
 	IsDatabaseConfigured() bool
30
+	IsDatabaseConfiguredByName(name string) bool
22
 	IsDorisConfigured() bool
31
 	IsDorisConfigured() bool
23
 	IsRedisConfigured() bool
32
 	IsRedisConfigured() bool
33
+
24
 	SetServiceName(name string)
34
 	SetServiceName(name string)
25
 	SetServiceVersion(version string)
35
 	SetServiceVersion(version string)
26
 	SetEnv(name string)
36
 	SetEnv(name string)
27
 }
37
 }
28
 
38
 
29
-// 根据启动参数设置环境变量
30
-func (c *Config) SetEnv(name string) {
31
-	if c.GetService().Env == "" {
32
-		c.GetService().Env = name
33
-	}
39
+// Config 主配置结构体 - 访问门面
40
+type Config struct {
41
+	initError error // 初始化错误
34
 }
42
 }
35
 
43
 
36
-// 设置微服务名称。。如果配置文件设置了,就按配置文件
37
-func (c *Config) SetServiceName(name string) {
38
-	if c.GetService().ServiceName == "" {
39
-		c.GetService().ServiceName = name
40
-	}
44
+// ========== 数据库相关方法(更新) ==========
41
 
45
 
46
+// GetDatabases 获取所有数据库配置
47
+func (c *Config) GetDatabases() *subconfigs.DatabasesConfig {
48
+	if config := subconfigs.GetRegisteredConfig("databases"); config != nil {
49
+		if dbs, ok := config.(*subconfigs.DatabasesConfig); ok {
50
+			return dbs
51
+		}
52
+	}
53
+	return nil
42
 }
54
 }
43
 
55
 
44
-// 设置微服务版本号
45
-func (c *Config) SetServiceVersion(version string) {
56
+// GetDatabase 获取默认数据库配置(向后兼容)
57
+func (c *Config) GetDatabase() *subconfigs.DatabaseConfig {
58
+	dbs := c.GetDatabases()
59
+	if dbs == nil {
60
+		logger.Errorf("获取默认数据库连接配置发生错误:配置为空!")
61
+		return nil
62
+	}
63
+	return dbs.GetDefaultDatabase()
64
+}
46
 
65
 
47
-	c.GetService().ServiceVersion = version
66
+// GetDatabaseConfig 按名称获取数据库配置
67
+func (c *Config) GetDatabaseConfig(name string) *subconfigs.DatabaseConfig {
68
+	dbs := c.GetDatabases()
69
+	if dbs == nil {
70
+		return nil
71
+	}
72
+	return dbs.GetDatabase(name)
48
 }
73
 }
49
 
74
 
50
-// Config 主配置结构体 - 访问门面
51
-type Config struct {
52
-	initError error // 初始化错误
75
+// IsDatabaseConfigured 检查默认数据库是否配置
76
+func (c *Config) IsDatabaseConfigured() bool {
77
+	dbs := c.GetDatabases()
78
+	if dbs == nil {
79
+		return false
80
+	}
81
+	return dbs.IsConfigured()
53
 }
82
 }
54
 
83
 
55
-// 实现IConfig接口 - 从注册表获取配置
56
-func (c *Config) GetDatabase() *subconfigs.DatabaseConfig {
57
-	if config := subconfigs.GetRegisteredConfig("database"); config != nil {
58
-		return config.(*subconfigs.DatabaseConfig)
84
+// IsDatabaseConfiguredByName 检查指定名称的数据库是否配置
85
+func (c *Config) IsDatabaseConfiguredByName(name string) bool {
86
+	dbs := c.GetDatabases()
87
+	if dbs == nil {
88
+		return false
59
 	}
89
 	}
60
-	return nil
90
+	return dbs.IsConfigured()
61
 }
91
 }
62
 
92
 
93
+// ========== 其他配置方法(保持不变) ==========
94
+
63
 func (c *Config) GetRedis() *subconfigs.RedisConfig {
95
 func (c *Config) GetRedis() *subconfigs.RedisConfig {
64
 	if config := subconfigs.GetRegisteredConfig("redis"); config != nil {
96
 	if config := subconfigs.GetRegisteredConfig("redis"); config != nil {
65
 		return config.(*subconfigs.RedisConfig)
97
 		return config.(*subconfigs.RedisConfig)
120
 	return c.initError
152
 	return c.initError
121
 }
153
 }
122
 
154
 
123
-// GetService 包级便捷函数 - 获取服务配置
124
-func GetService() *subconfigs.ServiceConfig {
125
-	// 直接使用全局的 cfgInstance,假设初始化已完成
155
+// 实现 IConfig 接口的其他方法
156
+func (c *Config) IsDorisConfigured() bool {
157
+	doris := c.GetDoris()
158
+	return doris != nil && doris.IsConfigured()
159
+}
160
+
161
+func (c *Config) IsRedisConfigured() bool {
162
+	redis := c.GetRedis()
163
+	return redis != nil && redis.IsConfigured()
164
+}
165
+
166
+// 设置方法
167
+func (c *Config) SetEnv(name string) {
168
+	if c.GetService().Env == "" {
169
+		c.GetService().Env = name
170
+	}
171
+}
172
+
173
+func (c *Config) SetServiceName(name string) {
174
+	if c.GetService().ServiceName == "" {
175
+		c.GetService().ServiceName = name
176
+	}
177
+}
178
+
179
+func (c *Config) SetServiceVersion(version string) {
180
+	c.GetService().ServiceVersion = version
181
+}
182
+
183
+// ========== 包级便捷函数(更新) ==========
184
+
185
+// GetDatabases 包级便捷函数 - 获取所有数据库配置
186
+func GetDatabases() *subconfigs.DatabasesConfig {
126
 	if cfgInstance == nil {
187
 	if cfgInstance == nil {
127
-		// 这种情况不应该发生,但为了安全返回默认值
128
-		return &subconfigs.ServiceConfig{}
188
+		return nil
129
 	}
189
 	}
130
-	return cfgInstance.GetService()
190
+	return cfgInstance.GetDatabases()
131
 }
191
 }
132
 
192
 
133
-// GetDatabase 包级便捷函数 - 获取数据库配置
193
+// GetDatabase 包级便捷函数 - 获取默认数据库配置(向后兼容)
134
 func GetDatabase() *subconfigs.DatabaseConfig {
194
 func GetDatabase() *subconfigs.DatabaseConfig {
135
 	if cfgInstance == nil {
195
 	if cfgInstance == nil {
136
 		return &subconfigs.DatabaseConfig{}
196
 		return &subconfigs.DatabaseConfig{}
138
 	return cfgInstance.GetDatabase()
198
 	return cfgInstance.GetDatabase()
139
 }
199
 }
140
 
200
 
201
+// GetDatabaseConfig 包级便捷函数 - 按名称获取数据库配置
202
+func GetDatabaseConfig(name string) *subconfigs.DatabaseConfig {
203
+	if cfgInstance == nil {
204
+		return nil
205
+	}
206
+	return cfgInstance.GetDatabaseConfig(name)
207
+}
208
+
141
 // GetRedis 包级便捷函数 - 获取Redis配置
209
 // GetRedis 包级便捷函数 - 获取Redis配置
142
 func GetRedis() *subconfigs.RedisConfig {
210
 func GetRedis() *subconfigs.RedisConfig {
143
 	if cfgInstance == nil {
211
 	if cfgInstance == nil {
167
 		return &subconfigs.MicroConfig{}
235
 		return &subconfigs.MicroConfig{}
168
 	}
236
 	}
169
 	return cfgInstance.GetMicro()
237
 	return cfgInstance.GetMicro()
170
-
171
 }
238
 }
172
 
239
 
173
 func GetAuth() *subconfigs.AuthConfig {
240
 func GetAuth() *subconfigs.AuthConfig {
177
 	return cfgInstance.GetAuth()
244
 	return cfgInstance.GetAuth()
178
 }
245
 }
179
 
246
 
247
+func GetService() *subconfigs.ServiceConfig {
248
+	if cfgInstance == nil {
249
+		return &subconfigs.ServiceConfig{}
250
+	}
251
+	return cfgInstance.GetService()
252
+}
253
+
254
+// ========== 单例管理 ==========
255
+
180
 var (
256
 var (
181
 	cfgInstance *Config
257
 	cfgInstance *Config
182
 	once        sync.Once
258
 	once        sync.Once
201
 	cfg, err := GetConfig()
277
 	cfg, err := GetConfig()
202
 	return cfg, err
278
 	return cfg, err
203
 }
279
 }
204
-
205
-// 实现 IConfig 接口的 IsDatabaseConfigured 方法
206
-func (c *Config) IsDatabaseConfigured() bool {
207
-
208
-	return c.GetDatabase().IsConfigured()
209
-}
210
-
211
-// 实现 IConfig 接口的 IsDorisConfigured 方法
212
-func (c *Config) IsDorisConfigured() bool {
213
-
214
-	return c.GetDoris().IsConfigured()
215
-}
216
-
217
-// 实现 IConfig 接口的 IsDorisConfigured 方法
218
-func (c *Config) IsRedisConfigured() bool {
219
-
220
-	return c.GetRedis().IsConfigured()
221
-}

+ 222
- 15
config/subconfigs/database_config.go Näytä tiedosto

1
 package subconfigs
1
 package subconfigs
2
 
2
 
3
-import "fmt"
3
+import (
4
+	"fmt"
5
+	"log"
6
+)
7
+
8
+type DatabasesConfig struct {
9
+	BaseConfig
10
+	Databases map[string]*DatabaseConfig `yaml:"databases"`
11
+}
4
 
12
 
5
 // DatabaseConfig 数据库配置
13
 // DatabaseConfig 数据库配置
6
 type DatabaseConfig struct {
14
 type DatabaseConfig struct {
16
 	ConnMaxLifetime int    `yaml:"conn_max_lifetime"`
24
 	ConnMaxLifetime int    `yaml:"conn_max_lifetime"`
17
 }
25
 }
18
 
26
 
19
-// NewDatabaseConfig 创建数据库配置实例
20
-func NewDatabaseConfig() *DatabaseConfig {
21
-	return &DatabaseConfig{}
27
+// ========== DatabasesConfig 实现 ConfigLoader 接口 ==========
28
+
29
+// SetDefaults 设置默认值 - 实现 ConfigLoader 接口
30
+func (c *DatabasesConfig) SetDefaults() {
31
+	if c.Databases == nil {
32
+		c.Databases = make(map[string]*DatabaseConfig)
33
+		log.Println("⚠️  数据库配置为空,已初始化空的数据库配置")
34
+		return
35
+	}
36
+
37
+	// 为每个数据库配置设置默认值
38
+	for _, db := range c.Databases {
39
+		if db != nil {
40
+			db.SetDefaults()
41
+		}
42
+	}
43
+}
44
+
45
+func (c *DatabasesConfig) Load(data map[string]interface{}) error {
46
+	// 初始化
47
+	c.Databases = make(map[string]*DatabaseConfig)
48
+
49
+	// 遍历所有数据库配置
50
+	for dbName, dbData := range data {
51
+		dbDataMap, ok := dbData.(map[interface{}]interface{})
52
+		if !ok {
53
+			return fmt.Errorf("database '%s' config is not a map", dbName)
54
+		}
55
+
56
+		// 转换为 map[string]interface{}
57
+		stringMap := make(map[string]interface{})
58
+		for k, v := range dbDataMap {
59
+			if key, ok := k.(string); ok {
60
+				stringMap[key] = v
61
+			}
62
+		}
63
+
64
+		// 加载单个数据库配置
65
+		dbConfig := &DatabaseConfig{}
66
+		if err := dbConfig.Load(stringMap); err != nil {
67
+			return fmt.Errorf("failed to load database '%s' config: %v", dbName, err)
68
+		}
69
+
70
+		c.Databases[dbName] = dbConfig
71
+	}
72
+
73
+	// 设置默认值和验证
74
+	c.SetDefaults()
75
+	return c.Validate()
22
 }
76
 }
23
 
77
 
24
-// SetDefaults 设置默认值
78
+// ========== DatabaseConfig 实现 ConfigLoader 接口 ==========
79
+
80
+// SetDefaults 设置默认值 - 实现 ConfigLoader 接口
25
 func (c *DatabaseConfig) SetDefaults() {
81
 func (c *DatabaseConfig) SetDefaults() {
26
-	c.Type = "mysql"
27
-	c.Port = 3306
28
-	c.MaxOpenConns = 100
29
-	c.MaxIdleConns = 20
30
-	c.ConnMaxLifetime = 3600
82
+	if c.Type == "" {
83
+		c.Type = "mysql"
84
+	}
85
+	if c.Port == 0 {
86
+		c.Port = 3306
87
+	}
88
+	if c.MaxOpenConns == 0 {
89
+		c.MaxOpenConns = 100
90
+	}
91
+	if c.MaxIdleConns == 0 {
92
+		c.MaxIdleConns = 20
93
+	}
94
+	if c.ConnMaxLifetime == 0 {
95
+		c.ConnMaxLifetime = 3600
96
+	}
31
 }
97
 }
32
 
98
 
33
-// Load 从yaml数据加载
99
+// Load 从yaml数据加载 - 实现 ConfigLoader 接口
34
 func (c *DatabaseConfig) Load(data map[string]interface{}) error {
100
 func (c *DatabaseConfig) Load(data map[string]interface{}) error {
101
+	// 虽然可能不会被直接调用,但为了接口完整性还是要实现
35
 	return c.LoadFromYAML(data, c)
102
 	return c.LoadFromYAML(data, c)
36
 }
103
 }
37
 
104
 
38
-// Validate 验证配置
105
+// ========== 业务方法 ==========
106
+
107
+// Validate 验证配置(数据库配置)
39
 func (c *DatabaseConfig) Validate() error {
108
 func (c *DatabaseConfig) Validate() error {
40
 	if c.Type == "" {
109
 	if c.Type == "" {
41
 		return fmt.Errorf("database type is required")
110
 		return fmt.Errorf("database type is required")
42
 	}
111
 	}
112
+	if c.Host == "" {
113
+		return fmt.Errorf("database host is required")
114
+	}
115
+	if c.Port <= 0 || c.Port > 65535 {
116
+		return fmt.Errorf("invalid database port: %d", c.Port)
117
+	}
118
+	if c.Database == "" {
119
+		return fmt.Errorf("database name is required")
120
+	}
121
+	return nil
122
+}
123
+
124
+// Validate 验证配置(多数据库配置)
125
+func (c *DatabasesConfig) Validate() error {
126
+	if c.Databases == nil || len(c.Databases) == 0 {
127
+		log.Println("❌ 错误: 未找到任何数据库配置,请检查配置文件中的 'databases' 配置")
128
+		return fmt.Errorf("no database configurations found")
129
+	}
130
+
131
+	// 必须要有默认数据库
132
+	if _, exists := c.Databases["default"]; !exists {
133
+		availableDBs := c.GetAllDatabaseNames()
134
+		log.Printf("❌ 错误: 默认数据库未找到。可用的数据库: %v。请在配置文件中添加 'default' 数据库", availableDBs)
135
+		return fmt.Errorf("default database not found")
136
+	}
137
+
138
+	// 验证每个数据库配置
139
+	for name, db := range c.Databases {
140
+		if db == nil {
141
+			log.Printf("❌ 错误: 数据库 '%s' 配置为空", name)
142
+			return fmt.Errorf("database '%s' configuration is nil", name)
143
+		}
144
+
145
+		if err := db.Validate(); err != nil {
146
+			log.Printf("❌ 错误: 数据库 '%s' 验证失败: %v", name, err)
147
+			return fmt.Errorf("database '%s' validation failed: %v", name, err)
148
+		}
149
+	}
150
+
151
+	log.Printf("✅ 数据库配置验证通过,找到 %d 个数据库配置", len(c.Databases))
43
 	return nil
152
 	return nil
44
 }
153
 }
45
 
154
 
46
-// IsConfigured 判断是否已配置
155
+// IsConfigured 判断是否已配置(数据库配置)
47
 func (c *DatabaseConfig) IsConfigured() bool {
156
 func (c *DatabaseConfig) IsConfigured() bool {
48
-	return c.Host != "" && c.Port > 0 && c.Username != "" && c.Database != ""
157
+	if c.Host == "" {
158
+		log.Println("⚠️  警告: 数据库 Host 未配置")
159
+		return false
160
+	}
161
+	if c.Port <= 0 {
162
+		log.Println("⚠️  警告: 数据库 Port 未配置或无效")
163
+		return false
164
+	}
165
+	if c.Username == "" {
166
+		log.Println("⚠️  警告: 数据库 Username 未配置")
167
+		return false
168
+	}
169
+	if c.Database == "" {
170
+		log.Println("⚠️  警告: 数据库名称未配置")
171
+		return false
172
+	}
173
+	return true
174
+}
175
+
176
+// IsConfigured 判断是否已配置(多数据库配置)
177
+func (c *DatabasesConfig) IsConfigured() bool {
178
+	defaultDB := c.GetDefaultDatabase()
179
+	if defaultDB == nil {
180
+		log.Println("❌ 错误: 默认数据库不存在")
181
+		return false
182
+	}
183
+
184
+	if !defaultDB.IsConfigured() {
185
+		log.Println("❌ 错误: 默认数据库配置不完整")
186
+		return false
187
+	}
188
+
189
+	return true
190
+}
191
+
192
+// GetDefaultDatabase 获取默认数据库(必须存在)
193
+func (c *DatabasesConfig) GetDefaultDatabase() *DatabaseConfig {
194
+	if c.Databases == nil {
195
+		log.Println("❌ 错误: 尝试获取默认数据库时,数据库配置为空")
196
+		return nil
197
+	}
198
+
199
+	if db, exists := c.Databases["default"]; exists {
200
+		return db
201
+	}
202
+
203
+	// 如果没有名为default的,尝试返回第一个(但会记录警告)
204
+	for name, db := range c.Databases {
205
+		log.Printf("⚠️  警告: 未找到名为 'default' 的数据库,使用第一个数据库 '%s' 作为默认", name)
206
+		return db
207
+	}
208
+
209
+	log.Println("❌ 错误: 数据库中没有任何配置")
210
+	return nil
211
+}
212
+
213
+// GetDatabase 按名称获取数据库(为空时记录错误)
214
+func (c *DatabasesConfig) GetDatabase(name string) *DatabaseConfig {
215
+	if c.Databases == nil {
216
+		log.Printf("❌ 错误: 尝试获取数据库 '%s' 时,数据库配置为空", name)
217
+		return nil
218
+	}
219
+
220
+	db := c.Databases[name]
221
+	if db == nil {
222
+		availableDBs := c.GetAllDatabaseNames()
223
+		log.Printf("❌ 错误: 数据库 '%s' 不存在。可用的数据库: %v", name, availableDBs)
224
+	}
225
+
226
+	return db
227
+}
228
+
229
+// GetAllDatabaseNames 获取所有数据库名称
230
+func (c *DatabasesConfig) GetAllDatabaseNames() []string {
231
+	if c.Databases == nil {
232
+		log.Println("⚠️  警告: 尝试获取数据库名称时,数据库配置为空")
233
+		return []string{}
234
+	}
235
+
236
+	names := make([]string, 0, len(c.Databases))
237
+	for name := range c.Databases {
238
+		names = append(names, name)
239
+	}
240
+	return names
241
+}
242
+
243
+// GetDatabaseNamesWithoutDefault 获取除default外的所有数据库名称
244
+func (c *DatabasesConfig) GetDatabaseNamesWithoutDefault() []string {
245
+	if c.Databases == nil {
246
+		return []string{}
247
+	}
248
+
249
+	names := make([]string, 0, len(c.Databases)-1)
250
+	for name := range c.Databases {
251
+		if name != "default" {
252
+			names = append(names, name)
253
+		}
254
+	}
255
+	return names
49
 }
256
 }
50
 
257
 
51
 // 自动注册
258
 // 自动注册
52
 func init() {
259
 func init() {
53
-	Register("database", &DatabaseConfig{})
260
+	Register("databases", &DatabasesConfig{})
54
 }
261
 }

Loading…
Peruuta
Tallenna