go手写Redis(2)之配置读取

配置读取

定义好名称为 redis.conf

bind 0.0.0.0
port 6379
databases 16
appendonly yes
appendfilename appendonly.aof

  • 先通过 os.Open() 打开文件流
  • 创建配置文件对象 ServerProperties
  • 将读取到的数据存入到 Map 结构中
  • 通过 reflect.TypeOfreflect.ValueOf 获取到反射对象
  • 遍历类型的字段通过反射获取到字段的名称,再去 Map 中获取到数据设置到对应的数据中
// ServerProperties 定义全局的配置对象
type ServerProperties struct {
	Bind              string `cfg:"bind"`       //绑定ip地址
	Port              int    `cfg:"port"`       //端口
	AppendOnly        bool   `cfg:"appendonly"` //是否开启aof
	AppendFilename    string `cfg:"appendfilename"`//aof名称的名称
	AppendFsync       string `cfg:"appendfsync"`
	MaxClients        int    `cfg:"maxclients"`  //最大客户端数量
	RequirePass       string `cfg:"requirepass"` //是否要求密码
	Databases         int    `cfg:"databases"`   //数据库的数量
	RDBFilename       string `cfg:"dbfilename"`  //rdb文件的名称
	MasterAuth        string `cfg:"masterauth"`  //master角色验证密码
	SlaveAnnouncePort int    `cfg:"slave-announce-port"`
	SlaveAnnounceIP   string `cfg:"slave-announce-ip"`
	ReplTimeout       int    `cfg:"repl-timeout"`

	Peers []string `cfg:"peers"`
	Self  string   `cfg:"self"`
}

// Properties 全局配置持有对象
var Properties *ServerProperties

// init 初始化服务端的配置信息,设置默认绑定地址和端口
func init() {
	// 默认配置对象
	Properties = &ServerProperties{
		Bind:       "127.0.0.1",
		Port:       6379,
		AppendOnly: false,
	}
}

// parse 将文件解析为配置对象
func parse(src io.Reader) *ServerProperties {
	config := &ServerProperties{}

	// 创建map
	rawMap := make(map[string]string)
	//获取到扫描器
	scanner := bufio.NewScanner(src)
	for scanner.Scan() {
		line := scanner.Text()
		if len(line) > 0 && strings.TrimLeft(line, " ")[0] == '#' {
			continue
		}
		pivot := strings.IndexAny(line, " ")
		if pivot > 0 && pivot < len(line)-1 { // separator found
			key := line[0:pivot]
			value := strings.Trim(line[pivot+1:], " ")
			rawMap[strings.ToLower(key)] = value
		}
	}

	//打印err
	if err := scanner.Err(); err != nil {
		logger.Fatal(err)
	}
	// 通过反射解析配置名称跟配置对象对应上
	t := reflect.TypeOf(config)
	v := reflect.ValueOf(config)
	//获取到字段的数量
	n := t.Elem().NumField()
	for i := 0; i < n; i++ {
		//通过反射获取到字段的类型
		field := t.Elem().Field(i)
		//获取到实际的字段操作对象
		fieldVal := v.Elem().Field(i)
		//获取到cfg的标签,获取到对应配置文件中的配置名称
		key, ok := field.Tag.Lookup("cfg")
		if !ok || strings.TrimLeft(key, " ") == "" {
			key = field.Name
		}
		//将配置的key存储到map中
		value, ok := rawMap[strings.ToLower(key)]
		if ok {
			// 获取到对应字段的类型
			switch field.Type.Kind() {
			case reflect.String:
				fieldVal.SetString(value)
			case reflect.Int:
				intValue, err := strconv.ParseInt(value, 10, 64)
				if err == nil {
					fieldVal.SetInt(intValue)
				}
			case reflect.Bool:
				boolValue := "yes" == value
				fieldVal.SetBool(boolValue)
			case reflect.Slice:
				//将逗号隔开的字符串解析为 Slice切片
				if field.Type.Elem().Kind() == reflect.String {
					slice := strings.Split(value, ",")
					fieldVal.Set(reflect.ValueOf(slice))
				}
			}
		}
	}
	return config
}

// SetupConfig 设置配置,根据配置文件的名称打开文件路径
func SetupConfig(configFilename string) {
	file, err := os.Open(configFilename)
	if err != nil {
		panic(err)
	}
	//方法退出时关闭文件
	defer func(file *os.File) {
		_ = file.Close()
	}(file)
	//解析文件成为 Properties 对象
	Properties = parse(file)
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值