ini.go
func Parse(stream io.Reader) Config {
	var cfg Config
	var curSection string

	scanner := bufio.NewScanner(bufio.NewReader(stream))
	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())
		if strings.HasPrefix(line, "#") || strings.HasPrefix(line, ";") {
			comment := strings.TrimLeft(line, ";# ")
			cfg.AddComment(curSection, comment)
		} else if len(line) > 0 {
			if m := iniSectionRe.FindStringSubmatch(line); len(m) > 0 {
				curSection = m[1]
			} else if m := iniOptionRe.FindStringSubmatch(line); len(m) > 0 {
				key := m[1]
				val := m[2]
				if !strings.Contains(val, "\"") {
					// If val does not contain any quote characers, we can make it
					// a quoted string and safely let strconv.Unquote sort out any
					// escapes
					val = "\"" + val + "\""
				}
				if val[0] == '"' {
					val, _ = strconv.Unquote(val)
				}

				cfg.Set(curSection, key, val)
			}
		}
	}
	return cfg
}
func Parse(stream io.Reader) Config {
	var cfg Config
	var curSection string

	scanner := bufio.NewScanner(bufio.NewReader(stream))
	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())
		if strings.HasPrefix(line, "#") || strings.HasPrefix(line, ";") {
			comment := strings.TrimLeft(line, ";# ")
			cfg.AddComment(curSection, comment)
		} else if len(line) > 0 {
			if m := iniSectionRe.FindStringSubmatch(line); len(m) > 0 {
				curSection = m[1]
			} else if m := iniOptionRe.FindStringSubmatch(line); len(m) > 0 {
				key := m[1]
				val := m[2]
				if !strings.Contains(val, "\"") {
					// If val does not contain any quote characers, we can make it
					// a quoted string and safely let strconv.Unquote sort out any
					// escapes
					val = "\"" + val + "\""
				}
				if val[0] == '"' {
					val, _ = strconv.Unquote(val)
				}

				cfg.Set(curSection, key, val)
			}
		}
	}
	return cfg
}
// Parse reads the given io.Reader and returns a parsed Config object.