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