Usage:
- Init(rc_file1,rc_file2...) 后面的会覆盖前面的
- Get(section)
在配置文件中可以使用COMMENT_FLAG
默认 #
来写注解.
package config import ( "fmt" "io/IoUtil" "log" "os" "regexp" "strings" ) var CONFIG map[string]map[string]string = make(map[string]map[string]string) const COMMENT_FLAG = "#" var RE_SESSION *regexp.Regexp = regexp.MustCompile("^\\[.+\\]$") var RE_KV *regexp.Regexp = regexp.MustCompile("^.+\\=.+$") func exists(file string) bool { if f,err := os.Open(file); err != nil && os.IsNotExist(err) { defer f.Close() return false } return true } func parse_line(line string) (string,interface{}) { comment_index := strings.Index(line,COMMENT_FLAG) if comment_index != -1 { line = line[0:comment_index] } if RE_SESSION.MatchString(line) { return "section",line[1 : len(line)-1] } if RE_KV.MatchString(line) { parts := strings.SplitN(line,"=",2) return "kv",map[string]string{strings.TrimSpace(parts[0]): strings.TrimSpace(parts[1])} } fmt.Fprintf(os.Stderr,"%s format error!\n",line) return "other",nil } func Get(section string) (map[string]string,error) { config,ok := CONFIG[section] if ok { return config,nil } return nil,fmt.Errorf("section %s not found",section) } func Sections() (sections []string) { for section,_ := range CONFIG { sections = append(sections,section) } return sections } func parse_rc_content(content string) map[string]map[string]string { config := make(map[string]map[string]string) lines := strings.FieldsFunc(content,func(char rune) bool { return strings.ContainsRune("\r\n",char) }) last_section := "" for _,line := range lines { line = strings.TrimSpace(line) if line == "" { continue } line_type,line_value := parse_line(line) switch { case line_type == "section": section := line_value.(string) if _,ok := config[section]; ok == false { config[section] = make(map[string]string) } last_section = section case line_type == "kv" && last_section != "": kv := line_value.(map[string]string) for k,v := range kv { config[last_section][k] = v } } } return config } func Init(rc_files ...string) { for _,rc_file := range rc_files { if !exists(rc_file) { continue } content_bytes,err := IoUtil.ReadFile(rc_file) if err != nil { log.Fatalln(err) } content := string(content_bytes) for section,configs := range parse_rc_content(content) { _,ok := CONFIG[section] if ok == false { CONFIG[section] = make(map[string]string) } for name,value := range configs { CONFIG[section][name] = value } } } }