config.go 3.2 KB

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