package main
import (
"bufio"
"fmt"
"log"
"os"
"reflect"
"strconv"
"strings"
)
type Config struct {
Section1 Section1 `ini:"section1"`
Section2 Section2 `ini:"section2"`
}
type Section1 struct {
Key1 string `ini:"key1"`
Key2 int `ini:"key2"`
}
type Section2 struct {
Key3 float64 `ini:"key3"`
Key4 bool `ini:"key4"`
}
func fieldName(fieldName string) func(string) bool {
return func(tag string) bool {
return strings.EqualFold(tag, fieldName)
}
}
func main() {
file, err := os.Open("config.ini")
if err != nil {
log.Fatalf("Failed to open file: %v", err)
}
defer file.Close()
cfg := Config{}
scanner := bufio.NewScanner(file)
currentSection := ""
v := reflect.ValueOf(&cfg).Elem()
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if line == "" || strings.HasPrefix(line, "#") {
continue
}
if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") {
currentSection = strings.Trim(line, "[]")
sectionField := v.FieldByNameFunc(fieldName(currentSection))
if !sectionField.IsValid() {
log.Printf("Invalid section: %s", currentSection)
}
} else {
parts := strings.SplitN(line, "=", 2)
if len(parts) != 2 {
log.Printf("Invalid key-value pair: %s", line)
continue
}
key := strings.TrimSpace(parts[0])
value := strings.TrimSpace(parts[1])
if currentSection == "" {
log.Printf("Key-value pair found outside of any section: %s", line)
continue
}
sectionField := v.FieldByNameFunc(fieldName(currentSection))
if !sectionField.IsValid() {
log.Printf("Invalid section: %s", currentSection)
continue
}
field := sectionField.FieldByNameFunc(fieldName(key))
if !field.IsValid() {
log.Printf("Invalid key: %s", key)
continue
}
switch field.Kind() {
case reflect.String:
field.SetString(value)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
intValue, err := strconv.ParseInt(value, 10, 64)
if err != nil {
log.Printf("Failed to parse int value for key %s: %v", key, err)
continue
}
field.SetInt(intValue)
case reflect.Float32, reflect.Float64:
floatValue, err := strconv.ParseFloat(value, 64)
if err != nil {
log.Printf("Failed to parse float value for key %s: %v", key, err)
continue
}
field.SetFloat(floatValue)
case reflect.Bool:
boolValue, err := strconv.ParseBool(value)
if err != nil {
log.Printf("Failed to parse bool value for key %s: %v", key, err)
continue
}
field.SetBool(boolValue)
default:
log.Printf("Unsupported field type for key %s", key)
}
}
}
if err := scanner.Err(); err != nil {
log.Fatalf("Error while scanning file: %v", err)
}
fmt.Printf("%+v\n", cfg)
}
[Section1]
key1 = value1
key2 = 100
[Section2]
key3 = 3.14
key4 = true