config.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. package config
  2. import (
  3. "bufio"
  4. "io"
  5. "os"
  6. "reflect"
  7. "strconv"
  8. "strings"
  9. "github.com/runningwater/go-redis/lib/logger"
  10. )
  11. // ServerProperties 定义了服务器的全局配置属性
  12. type ServerProperties struct {
  13. // Bind 服务器绑定的IP地址
  14. Bind string `cfg:"bind"`
  15. // Port 服务器监听的端口号
  16. Port int `cfg:"port"`
  17. // AppendOnly 是否启用AOF持久化模式
  18. AppendOnly bool `cfg:"appendOnly"`
  19. // AppendFilename AOF文件名
  20. AppendFilename string `cfg:"appendFilename"`
  21. // MaxClients 最大客户端连接数
  22. MaxClients int `cfg:"maxclients"`
  23. // RequirePass 访问服务器所需的密码
  24. RequirePass string `cfg:"requirepass"`
  25. // Databases 数据库数量
  26. Databases int `cfg:"databases"`
  27. // Peers 集群中其他节点地址列表
  28. Peers []string `cfg:"peers"`
  29. // Self 当前节点在集群中的地址
  30. Self string `cfg:"self"`
  31. }
  32. // Properties 持有全局配置属性的实例
  33. var Properties *ServerProperties
  34. func init() {
  35. // 默认配置
  36. Properties = &ServerProperties{
  37. Bind: "127.0.0.1",
  38. Port: 6379,
  39. AppendOnly: false,
  40. }
  41. }
  42. // parse 解析配置文件,将配置项映射到ServerProperties结构体中
  43. func parse(src io.Reader) *ServerProperties {
  44. config := &ServerProperties{}
  45. // 读取配置文件
  46. rawMap := make(map[string]string)
  47. scanner := bufio.NewScanner(src)
  48. for scanner.Scan() {
  49. line := scanner.Text()
  50. // 跳过注释行(以#开头的行)
  51. if len(line) > 0 && line[0] == '#' {
  52. continue
  53. }
  54. // 查找第一个空格位置,分离键和值
  55. pivot := strings.IndexAny(line, " ")
  56. if pivot > 0 && pivot < len(line)-1 { // 找到分隔符
  57. key := line[0:pivot]
  58. value := strings.Trim(line[pivot+1:], " ")
  59. rawMap[strings.ToLower(key)] = value
  60. }
  61. }
  62. if err := scanner.Err(); err != nil {
  63. logger.Fatal(err)
  64. }
  65. // 使用反射解析配置格式
  66. t := reflect.TypeOf(config)
  67. v := reflect.ValueOf(config)
  68. n := t.Elem().NumField()
  69. for i := 0; i < n; i++ {
  70. field := t.Elem().Field(i)
  71. fieldVal := v.Elem().Field(i)
  72. // 获取cfg标签作为配置键名,如果没有则使用字段名
  73. key, ok := field.Tag.Lookup("cfg")
  74. if !ok {
  75. key = field.Name
  76. }
  77. value, ok := rawMap[strings.ToLower(key)]
  78. if ok {
  79. // 根据字段类型填充配置值
  80. switch field.Type.Kind() {
  81. case reflect.String:
  82. fieldVal.SetString(value)
  83. case reflect.Int:
  84. intValue, err := strconv.ParseInt(value, 10, 64)
  85. if err == nil {
  86. fieldVal.SetInt(intValue)
  87. }
  88. case reflect.Bool:
  89. boolValue := value == "yes"
  90. fieldVal.SetBool(boolValue)
  91. case reflect.Slice:
  92. if field.Type.Elem().Kind() == reflect.String {
  93. slice := strings.Split(value, ",")
  94. fieldVal.Set(reflect.ValueOf(slice))
  95. }
  96. default:
  97. // 未处理的类型
  98. panic("unhandled default case")
  99. }
  100. }
  101. }
  102. return config
  103. }
  104. // SetupConfig 读取配置文件并将属性存储到Properties变量中
  105. func SetupConfig(configFilename string) {
  106. file, err := os.Open(configFilename)
  107. if err != nil {
  108. panic(err)
  109. }
  110. defer func() {
  111. closeErr := file.Close()
  112. if closeErr != nil {
  113. panic(closeErr)
  114. }
  115. }()
  116. Properties = parse(file)
  117. }