add config

Path: .git/config
[core]
	repositoryformatversion = 0
	filemode = true
	bare = false
This commit is contained in:
kingecg 2025-06-05 20:43:16 +08:00
parent 41e4973850
commit 651256a0c2
6 changed files with 234 additions and 0 deletions

0
config/.gitkeep Normal file
View File

91
config/config.go Normal file
View File

@ -0,0 +1,91 @@
package config
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"sync"
"encoding/json"
"gopkg.in/yaml.v2"
)
// Config 系统配置结构体
type Config struct {
Server ServerConfig `yaml:"server" json:"server"`
Storage StorageConfig `yaml:"storage" json:"storage"`
}
// ServerConfig 服务器配置
type ServerConfig struct {
Host string `yaml:"host" json:"host"`
Port int `yaml:"port" json:"port"`
}
// StorageConfig 存储配置
type StorageConfig struct {
Engine string `yaml:"engine" json:"engine"`
DataPath string `yaml:"dataPath" json:"dataPath"`
}
var (
configInstance *Config
once sync.Once
)
// NewDefaultConfig 创建默认配置
func NewDefaultConfig() *Config {
return &Config{
Server: ServerConfig{
Host: "0.0.0.0",
Port: 27017,
},
Storage: StorageConfig{
Engine: "memory",
DataPath: "/var/lib/goaidb",
},
}
}
// ParseConfig 解析配置文件
// 支持JSON和YAML格式
// 返回解析后的配置对象和错误信息
func ParseConfig(filePath string) (*Config, error) {
// 检查文件是否存在
if _, err := os.Stat(filePath); os.IsNotExist(err) {
return nil, fmt.Errorf("配置文件不存在: %s", filePath)
}
// 读取文件内容
data, err := ioutil.ReadFile(filePath)
if err != nil {
return nil, fmt.Errorf("读取配置文件失败: %v", err)
}
// 根据文件扩展名选择解析方式
var cfg Config
switch filepath.Ext(filePath) {
case ".json":
if err := json.Unmarshal(data, &cfg); err != nil {
return nil, fmt.Errorf("JSON解析失败: %v", err)
}
case ".yaml", ".yml":
if err := yaml.Unmarshal(data, &cfg); err != nil {
return nil, fmt.Errorf("YAML解析失败: %v", err)
}
default:
return nil, fmt.Errorf("不支持的配置文件格式")
}
return &cfg, nil
}
// GetConfig 获取全局配置实例
func GetConfig() *Config {
once.Do(func() {
configInstance = NewDefaultConfig()
})
return configInstance
}

104
config/config_test.go Normal file
View File

@ -0,0 +1,104 @@
package config
import (
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
)
func TestParseConfig_JSON(t *testing.T) {
// 创建临时JSON配置文件
tmpFile, err := os.CreateTemp("", "*.json")
assert.NoError(t, err)
defer os.Remove(tmpFile.Name())
// 写入测试配置内容
testConfig := `{
"server": {
"host": "127.0.0.1",
"port": 8080
},
"storage": {
"engine": "rocksdb",
"dataPath": "/test/data"
}
}`
_, err = tmpFile.WriteString(testConfig)
assert.NoError(t, err)
tmpFile.Close()
// 测试解析功能
cfg, err := ParseConfig(tmpFile.Name())
assert.NoError(t, err)
assert.NotNil(t, cfg)
assert.Equal(t, "127.0.0.1", cfg.Server.Host)
assert.Equal(t, 8080, cfg.Server.Port)
assert.Equal(t, "rocksdb", cfg.Storage.Engine)
assert.Equal(t, "/test/data", cfg.Storage.DataPath)
}
func TestParseConfig_YAML(t *testing.T) {
// 创建临时YAML配置文件
tmpFile, err := os.CreateTemp("", "*.yaml")
assert.NoError(t, err)
defer os.Remove(tmpFile.Name())
// 写入测试配置内容
testConfig := `server:
host: 127.0.0.1
port: 8080
storage:
engine: rocksdb
dataPath: /test/data`
_, err = tmpFile.WriteString(testConfig)
assert.NoError(t, err)
tmpFile.Close()
// 测试解析功能
cfg, err := ParseConfig(tmpFile.Name())
assert.NoError(t, err)
assert.NotNil(t, cfg)
assert.Equal(t, "127.0.0.1", cfg.Server.Host)
assert.Equal(t, 8080, cfg.Server.Port)
assert.Equal(t, "rocksdb", cfg.Storage.Engine)
assert.Equal(t, "/test/data", cfg.Storage.DataPath)
}
func TestParseConfig_Default(t *testing.T) {
// 测试默认配置
cfg := GetConfig()
assert.NotNil(t, cfg)
assert.Equal(t, "0.0.0.0", cfg.Server.Host)
assert.Equal(t, 27017, cfg.Server.Port)
assert.Equal(t, "memory", cfg.Storage.Engine)
assert.Equal(t, "/var/lib/goaidb", cfg.Storage.DataPath)
}
func TestParseConfig_InvalidFormat(t *testing.T) {
// 创建临时无效格式配置文件
tmpFile, err := os.CreateTemp("", "*.txt")
assert.NoError(t, err)
defer os.Remove(tmpFile.Name())
// 写入任意内容
_, err = tmpFile.WriteString("invalid config content")
assert.NoError(t, err)
tmpFile.Close()
// 测试不支持的格式
_, err = ParseConfig(tmpFile.Name())
assert.Error(t, err)
assert.Contains(t, err.Error(), "不支持的配置文件格式")
}
func TestParseConfig_FileNotFound(t *testing.T) {
// 测试不存在的文件
notExistFile := filepath.Join("not", "exist", "config.json")
_, err := ParseConfig(notExistFile)
assert.Error(t, err)
assert.Contains(t, err.Error(), "配置文件不存在")
}

View File

@ -0,0 +1,20 @@
# 00000: 配置设计实现
## 目标
- 设计配置文件结构,并实现配置文件解析功能。
- 配置文件需要支持json和yaml格式
- 实现完整的单元测试覆盖
## 子任务分解
- [x] 设计配置文件结构
- [x] 实现配置文件解析功能
- [x] 设计默认配置数据
- [x] 实现全局方法获取指定配置项的值
- [x] 实现JSON格式解析测试
- [x] 实现YAML格式解析测试
- [x] 实现默认配置测试
- [x] 实现错误处理测试
## 完成状态
✅ 已完成

8
go.mod
View File

@ -5,3 +5,11 @@ go 1.23
// 使MongoDB官方驱动进行测试 // 使MongoDB官方驱动进行测试
// replace github.com/mongodb/mongo-go-driver => github.com/mongodb/mongo-go-driver/v2 v2.0.0 // replace github.com/mongodb/mongo-go-driver => github.com/mongodb/mongo-go-driver/v2 v2.0.0
// require github.com/mongodb/mongo-go-driver/v2 v2.0.0 // require github.com/mongodb/mongo-go-driver/v2 v2.0.0
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/testify v1.10.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

11
go.sum Normal file
View File

@ -0,0 +1,11 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=