### Install the package Source: https://github.com/burntsushi/toml/blob/master/README.md Add the library to your project using the go get command. ```bash go get github.com/BurntSushi/toml@latest ``` -------------------------------- ### Install and run tomlv Source: https://github.com/burntsushi/toml/blob/master/cmd/tomlv/README.md Install the tool via Go and validate a specific TOML file. ```bash $ go install github.com/BurntSushi/toml/cmd/tomlv@master $ tomlv some-toml-file.toml ``` -------------------------------- ### Install and use the validator CLI Source: https://github.com/burntsushi/toml/blob/master/README.md Install the tomlv tool to validate TOML files from the command line. ```bash go install github.com/BurntSushi/toml/cmd/tomlv@latest tomlv some-toml-file.toml ``` -------------------------------- ### Format TOML Keys Example Source: https://github.com/burntsushi/toml/blob/master/_autodocs/metadata-api.md Demonstrates how Key.String() handles simple, spaced, and nested keys. ```go package main import ( "fmt" "github.com/BurntSushi/toml" ) func main() { k1 := toml.Key{"simple"} fmt.Println(k1.String()) // "simple" k2 := toml.Key{"with space"} fmt.Println(k2.String()) // "\"with space\"" k3 := toml.Key{"a", "b", "c"} fmt.Println(k3.String()) // "a.b.c" } ``` -------------------------------- ### TOML Configuration Example Source: https://github.com/burntsushi/toml/blob/master/_autodocs/00-START-HERE.md A sample TOML file demonstrating basic key-value pairs, tables, and arrays of tables. ```toml # Comments start with # title = "Example Config" enabled = true port = 8080 timeout = "30s" [database] host = "localhost" port = 5432 [[servers]] name = "web1" ip = "192.168.1.1" [[servers]] name = "web2" ip = "192.168.1.2" ``` -------------------------------- ### Custom Marshaler Implementation Source: https://github.com/burntsushi/toml/blob/master/_autodocs/encoding-functions.md Example demonstrating a custom type implementing the Marshaler interface to control its TOML representation. ```go package main import ( "fmt" "github.com/BurntSushi/toml" ) type CustomValue struct { Raw string } func (cv CustomValue) MarshalTOML() ([]byte, error) { return []byte(fmt.Sprintf(`"%s"`, cv.Raw)), nil } func main() { val := CustomValue{Raw: "custom content"} bytes, _ := toml.Marshal(map[string]interface{}{"value": val}) fmt.Println(string(bytes)) } ``` -------------------------------- ### Invalid table redefinition examples Source: https://github.com/burntsushi/toml/blob/master/internal/toml-test/specs/v1.1.0.md Tables cannot be defined more than once. ```toml # DO NOT DO THIS [fruit] apple = "red" [fruit] orange = "orange" ``` ```toml # DO NOT DO THIS EITHER [fruit] apple = "red" [fruit.apple] texture = "smooth" ``` -------------------------------- ### Invalid TOML Key/Value Pair Examples Source: https://github.com/burntsushi/toml/blob/master/internal/toml-test/specs/v1.1.0.md Examples of invalid syntax including missing values and multiple pairs on a single line. ```toml key = # INVALID ``` ```toml first = "Tom" last = "Preston-Werner" # INVALID ``` -------------------------------- ### Invalid Float Examples Source: https://github.com/burntsushi/toml/blob/master/internal/toml-test/specs/v1.1.0.md Examples of syntactically incorrect float definitions in TOML. ```toml # INVALID FLOATS invalid_float_1 = .7 invalid_float_2 = 7. invalid_float_3 = 3.e+20 ``` -------------------------------- ### Duplicate Key Error Example Source: https://github.com/burntsushi/toml/blob/master/_autodocs/error-handling.md Example of a TOML structure that triggers a duplicate key error due to incompatible type definitions. ```toml fruit = [] # fruit is an array [[fruit]] # ERROR: cannot use as array of tables name = "apple" ``` -------------------------------- ### Invalid Key Definitions Source: https://github.com/burntsushi/toml/blob/master/internal/toml-test/specs/v1.0.0.md Examples of invalid key redefinitions or conflicting structures. ```toml # DO NOT DO THIS name = "Tom" name = "Pradyun" ``` ```toml # THIS WILL NOT WORK spelling = "favorite" "spelling" = "favourite" ``` ```toml # This makes the key "fruit" into a table. fruit.apple.smooth = true # So then you can add to the table "fruit" like so: fruit.orange = 2 ``` ```toml # THE FOLLOWING IS INVALID # This defines the value of fruit.apple to be an integer. fruit.apple = 1 # But then this treats fruit.apple like it's a table. # You can't turn an integer into a table. fruit.apple.smooth = true ``` -------------------------------- ### Equivalent standard table definitions Source: https://github.com/burntsushi/toml/blob/master/internal/toml-test/specs/v1.0.0.md Standard table syntax equivalent to the provided inline table examples. ```toml [name] first = "Tom" last = "Preston-Werner" [point] x = 1 y = 2 [animal] type.name = "pug" ``` -------------------------------- ### JSON mapping of dotted integer keys Source: https://github.com/burntsushi/toml/blob/master/internal/toml-test/specs/v1.1.0.md The JSON representation of the dotted integer key example. ```json { "3": { "14159": "pi" } } ``` -------------------------------- ### Get Key String Representation Source: https://github.com/burntsushi/toml/blob/master/_autodocs/metadata-api.md Returns the string representation of the key, applying quotes and escaping for special characters. ```go func (k Key) String() string ``` -------------------------------- ### Valid Float Representations Source: https://github.com/burntsushi/toml/blob/master/internal/toml-test/specs/v1.1.0.md Examples of valid TOML floats using fractional parts, exponents, or both. ```toml # fractional flt1 = +1.0 flt2 = 3.1415 flt3 = -0.01 # exponent flt4 = 5e+22 flt5 = 1e06 flt6 = -2E-2 # both flt7 = 6.626e-34 ``` -------------------------------- ### Define TOML integers Source: https://github.com/burntsushi/toml/blob/master/internal/toml-test/specs/v1.1.0.md Examples of basic integer definitions including positive, negative, and zero values. ```toml int1 = +99 int2 = 42 int3 = 0 int4 = -17 ``` -------------------------------- ### Use Key Type Source: https://github.com/burntsushi/toml/blob/master/_autodocs/types-and-interfaces.md Create a Key and convert it to its string representation. ```go key := toml.Key{"database", "server", "host"} fmt.Println(key.String()) // "database.server.host" ``` -------------------------------- ### Plugin Configuration System Source: https://github.com/burntsushi/toml/blob/master/_autodocs/complete-examples.md Demonstrates a dynamic configuration pattern where plugin-specific settings are decoded using toml.Primitive based on the plugin index. ```go package main import ( "fmt" "github.com/BurntSushi/toml" ) type PluginConfig struct { Name string Enabled bool Settings toml.Primitive // Unknown plugin-specific settings } type AppConfig struct { AppName string Plugins []PluginConfig } func loadPlugins(data string) (AppConfig, error) { var cfg AppConfig md, err := toml.Decode(data, &cfg) if err != nil { return cfg, fmt.Errorf("parse error: %w", err) } // Process each plugin for i, plugin := range cfg.Plugins { fmt.Printf("Plugin %d: %s (enabled=%v)\n", i+1, plugin.Name, plugin.Enabled, ) // Get plugin-specific type pluginKey := []string{"plugins", fmt.Sprintf("%d", i), "settings"} pluginType := md.Type(pluginKey...) if pluginType == "Hash" { var settings map[string]interface{} md.PrimitiveDecode(plugin.Settings, &settings) fmt.Printf(" Settings: %v\n", settings) } } return cfg, nil } func main() { tomlData := ` app_name = "PluginHost" [[plugins]] name = "auth" enabled = true [plugins.settings] provider = "oauth2" timeout = "5s" [[plugins]] name = "cache" enabled = true [plugins.settings] backend = "redis" ttl = "1h" ` cfg, err := loadPlugins(tomlData) if err != nil { fmt.Println("Error:", err) return } fmt.Printf("\nLoaded %d plugins\n", len(cfg.Plugins)) } ``` -------------------------------- ### Provide Sensible Defaults Source: https://github.com/burntsushi/toml/blob/master/_autodocs/performance-and-best-practices.md Initialize configuration structs with default values before decoding the TOML file to ensure all fields have valid states. ```go type Config struct { Name string Port int Timeout time.Duration MaxConn int EnableCache bool } func defaultConfig() Config { return Config{ Name: "app", Port: 8080, Timeout: 30 * time.Second, MaxConn: 100, EnableCache: true, } } func loadConfig(path string) (Config, error) { cfg := defaultConfig() if _, err := toml.DecodeFile(path, &cfg); err != nil { return Config{}, err } return cfg, nil } ``` -------------------------------- ### Parse environment-specific server configuration in Go Source: https://github.com/burntsushi/toml/blob/master/_autodocs/complete-examples.md Illustrates handling multiple environment configurations within a single TOML file and selecting the appropriate struct at runtime. ```go package main import ( "fmt" "github.com/BurntSushi/toml" "net" "time" ) type ServerConfig struct { Address string Port int TLSEnabled bool TLSCert string TLSKey string ReadTimeout time.Duration IdleTimeout time.Duration } type AppConfig struct { Environment string Development ServerConfig Staging ServerConfig Production ServerConfig } func main() { tomlData := ` environment = "production" [development] address = "127.0.0.1" port = 8000 tls_enabled = false read_timeout = "30s" idle_timeout = "1m" [staging] address = "0.0.0.0" port = 8000 tls_enabled = true tls_cert = "/etc/certs/staging.crt" tls_key = "/etc/certs/staging.key" read_timeout = "30s" idle_timeout = "1m" [production] address = "0.0.0.0" port = 443 tls_enabled = true tls_cert = "/etc/certs/prod.crt" tls_key = "/etc/certs/prod.key" read_timeout = "30s" idle_timeout = "5m" ` var cfg AppConfig toml.Unmarshal([]byte(tomlData), &cfg) var selected ServerConfig switch cfg.Environment { case "development": selected = cfg.Development case "staging": selected = cfg.Staging case "production": selected = cfg.Production } fmt.Printf("Running in %s mode\n", cfg.Environment) fmt.Printf("Server: %s:%d\n", selected.Address, selected.Port) fmt.Printf("TLS: %v\n", selected.TLSEnabled) } ``` -------------------------------- ### Load TOML Configuration in Go Source: https://github.com/burntsushi/toml/blob/master/_autodocs/complete-examples.md Demonstrates parsing a TOML file into a struct, checking for undecoded keys, and applying default values. ```go package main import ( "fmt" "github.com/BurntSushi/toml" "os" "path/filepath" ) type AppConfig struct { Debug bool Port int Paths struct { Data string Logs string Uploads string } } func loadConfig(configFile string) (*AppConfig, error) { cfg := &AppConfig{} // Try to load config file if _, err := os.Stat(configFile); err == nil { md, err := toml.DecodeFile(configFile, cfg) if err != nil { return nil, fmt.Errorf("failed to parse %s: %w", configFile, err) } // Check for unexpected keys if undecoded := md.Undecoded(); len(undecoded) > 0 { fmt.Printf("Warning: unexpected keys in config: %v\n", undecoded) } } else if !os.IsNotExist(err) { return nil, err } // Apply defaults if not set if cfg.Port == 0 { cfg.Port = 8080 } if cfg.Paths.Data == "" { cfg.Paths.Data = "./data" } if cfg.Paths.Logs == "" { cfg.Paths.Logs = "./logs" } if cfg.Paths.Uploads == "" { cfg.Paths.Uploads = "./uploads" } return cfg, nil } func main() { cfg, err := loadConfig("config.toml") if err != nil { fmt.Printf("Error loading config: %v\n", err) // Use defaults and continue cfg = &AppConfig{ Port: 8080, Paths: struct { Data string Logs string Uploads string }{ Data: "./data", Logs: "./logs", Uploads: "./uploads", }, } } fmt.Printf("Config loaded:\n") fmt.Printf(" Debug: %v\n", cfg.Debug) fmt.Printf(" Port: %d\n", cfg.Port) fmt.Printf(" Data path: %s\n", cfg.Paths.Data) } ``` -------------------------------- ### Load Configuration from File Source: https://github.com/burntsushi/toml/blob/master/_autodocs/00-START-HERE.md Decodes a TOML file directly into a struct. Requires a pre-defined configuration struct. ```go var cfg Config if _, err := toml.DecodeFile("config.toml", &cfg); err != nil { log.Fatal(err) } ``` -------------------------------- ### JSON representation of dotted keys Source: https://github.com/burntsushi/toml/blob/master/internal/toml-test/specs/v1.1.0.md The resulting JSON structure for the provided dotted key example. ```json { "name": "Orange", "physical": { "color": "orange", "shape": "round" }, "site": { "google.com": true } } ``` -------------------------------- ### JSON representation of nested arrays Source: https://github.com/burntsushi/toml/blob/master/internal/toml-test/specs/v1.0.0.md The JSON structure corresponding to the nested array of tables example. ```json { "fruits": [ { "name": "apple", "physical": { "color": "red", "shape": "round" }, "varieties": [ { "name": "red delicious" }, { "name": "granny smith" } ] }, { "name": "banana", "varieties": [ { "name": "plantain" } ] } ] } ``` -------------------------------- ### Migrate from deprecated aliases Source: https://github.com/burntsushi/toml/blob/master/_autodocs/types-and-interfaces.md Comparison showing the deprecated approach versus the preferred standard library approach. ```go // Deprecated: func (t MyType) MarshalText() ([]byte, error) { ... } // Preferred: func (t MyType) MarshalText() ([]byte, error) { ... } ``` -------------------------------- ### Validate Configuration After Decoding Source: https://github.com/burntsushi/toml/blob/master/_autodocs/performance-and-best-practices.md Check for undecoded keys and validate business logic constraints immediately after loading the configuration. ```go package main import ( "fmt" "github.com/BurntSushi/toml" ) func loadAndValidateConfig(path string) error { var cfg AppConfig md, err := toml.DecodeFile(path, &cfg) if err != nil { return err } // Check for unexpected keys if undecoded := md.Undecoded(); len(undecoded) > 0 { return fmt.Errorf("unexpected config keys: %v", undecoded) } // Validate business logic if cfg.Port < 1 || cfg.Port > 65535 { return fmt.Errorf("invalid port: %d", cfg.Port) } return nil } ``` -------------------------------- ### Define the root table Source: https://github.com/burntsushi/toml/blob/master/internal/toml-test/specs/v1.1.0.md The root table starts at the beginning of the document and ends before the first header. ```toml # Top-level table begins. name = "Fido" breed = "pug" # Top-level table ends. [owner] name = "Regina Dogman" member_since = 1999-08-04 ``` -------------------------------- ### Invalid TOML: Out of order definition Source: https://github.com/burntsushi/toml/blob/master/internal/toml-test/specs/v1.1.0.md Example of an invalid TOML document where a subtable is defined before its parent array. ```toml # INVALID TOML DOC [fruit.physical] # subtable, but to which parent element should it belong? color = "red" shape = "round" [[fruit]] # parser must throw an error upon discovering that "fruit" is # an array rather than a table name = "apple" ``` -------------------------------- ### Validate Configuration Files Source: https://github.com/burntsushi/toml/blob/master/_autodocs/quick-reference.md Use metadata from decoding to reject unexpected keys and validate configuration values. ```go func LoadConfig(path string) (Config, error) { var cfg Config md, err := toml.DecodeFile(path, &cfg) if err != nil { return Config{}, err } // Reject unexpected keys if undecoded := md.Undecoded(); len(undecoded) > 0 { return Config{}, fmt.Errorf("unexpected keys: %v", undecoded) } // Validate values if cfg.Port < 1 || cfg.Port > 65535 { return Config{}, fmt.Errorf("invalid port: %d", cfg.Port) } return cfg, nil } ``` -------------------------------- ### Parse simple TOML configuration in Go Source: https://github.com/burntsushi/toml/blob/master/_autodocs/complete-examples.md Demonstrates unmarshaling a basic TOML string into a flat Go struct. ```go package main import ( "fmt" "github.com/BurntSushi/toml" ) type Config struct { Name string Version string Debug bool } func main() { tomlData := ` name = "MyApp" version = "1.0.0" debug = true ` var cfg Config err := toml.Unmarshal([]byte(tomlData), &cfg) if err != nil { fmt.Println("Error:", err) return } fmt.Printf("App: %s v%s (debug=%v)\n", cfg.Name, cfg.Version, cfg.Debug) } ``` -------------------------------- ### Recommended dotted key ordering Source: https://github.com/burntsushi/toml/blob/master/internal/toml-test/specs/v1.1.0.md Grouping related dotted keys together is the recommended practice. ```toml # RECOMMENDED apple.type = "fruit" apple.skin = "thin" apple.color = "red" orange.type = "fruit" orange.skin = "thick" orange.color = "orange" ``` -------------------------------- ### Demonstrate Field Visibility and Mapping Source: https://github.com/burntsushi/toml/blob/master/_autodocs/struct-field-mapping.md Shows how exported fields are decoded while private fields are ignored during the unmarshaling process. ```go package main import ( "fmt" "github.com/BurntSushi/toml" ) type Config struct { Title string // Exported: will be decoded Enabled bool // Exported: will be decoded privateKey string // Private: ignored } func main() { tomlData := ` title = "My Config" enabled = true privateKey = "secret" // This key won't be used ` var cfg Config toml.Unmarshal([]byte(tomlData), &cfg) fmt.Println("Title:", cfg.Title) // "My Config" fmt.Println("Enabled:", cfg.Enabled) // true fmt.Println("Private:", cfg.privateKey) // "" (not decoded) } ``` -------------------------------- ### Represent nested TOML arrays as JSON Source: https://github.com/burntsushi/toml/blob/master/internal/toml-test/specs/v1.1.0.md Shows the JSON mapping for the nested TOML array of tables example. ```json { "fruits": [ { "name": "apple", "physical": { "color": "red", "shape": "round" }, "varieties": [{ "name": "red delicious" }, { "name": "granny smith" }] }, { "name": "banana", "varieties": [{ "name": "plantain" }] } ] } ``` -------------------------------- ### Inspect Runtime Types Source: https://github.com/burntsushi/toml/blob/master/_autodocs/README.md Use the MetaData API to iterate over keys and inspect their types. ```go var config map[string]interface{} md, _ := toml.Decode(tomlData, &config) for _, key := range md.Keys() { fmt.Printf("%s: %s\n", key.String(), md.Type(key...)) } ``` -------------------------------- ### Define TOML String Formats Source: https://github.com/burntsushi/toml/blob/master/_autodocs/quick-reference.md Demonstrates basic, literal, and multi-line string definitions in TOML. ```toml # Basic string (escapes processed) basic = "line1\nline2" # Literal string (no escapes) literal = 'C:\Users\Name' # Multi-line basic (preserves newlines) multi = """ Line 1 Line 2 """ # Multi-line literal multi_lit = ''' Raw text: No escapes \n just text ''' ``` -------------------------------- ### Initialize a new TOML Encoder Source: https://github.com/burntsushi/toml/blob/master/_autodocs/encoder.md Creates an encoder instance targeting an io.Writer, such as os.Stdout. ```go package main import ( "os" "github.com/BurntSushi/toml" ) func main() { enc := toml.NewEncoder(os.Stdout) // Use enc.Encode(value) to write TOML } ``` -------------------------------- ### Define TOML Comments Source: https://github.com/burntsushi/toml/blob/master/internal/toml-test/specs/v1.0.0.md Comments start with a hash symbol and continue to the end of the line, unless inside a string. ```toml # This is a full-line comment key = "value" # This is a comment at the end of a line another = "# This is not a comment" ``` -------------------------------- ### Initialize NewDecoder Source: https://github.com/burntsushi/toml/blob/master/_autodocs/decoder.md Creates a new decoder instance to read from an io.Reader. ```go func NewDecoder(r io.Reader) *Decoder ``` ```go package main import ( "strings" "github.com/BurntSushi/toml" ) func main() { tomlData := `title = "Example"` dec := toml.NewDecoder(strings.NewReader(tomlData)) } ``` -------------------------------- ### Invalid TOML: Appending to static array Source: https://github.com/burntsushi/toml/blob/master/internal/toml-test/specs/v1.1.0.md Example of an invalid TOML document where an attempt is made to append to a statically defined array. ```toml # INVALID TOML DOC fruits = [] [[fruits]] # Not allowed ``` -------------------------------- ### Define tables using dotted keys Source: https://github.com/burntsushi/toml/blob/master/internal/toml-test/specs/v1.0.0.md Demonstrates how to define nested tables using dot-separated keys. ```toml fruit.apple.color = "red" # Defines a table named fruit # Defines a table named fruit.apple fruit.apple.taste.sweet = true # Defines a table named fruit.apple.taste # fruit and fruit.apple were already created ``` -------------------------------- ### Implement Custom Marshaler and Unmarshaler Source: https://github.com/burntsushi/toml/blob/master/_autodocs/types-and-interfaces.md Demonstrates implementing the Marshaler and Unmarshaler interfaces for a custom struct to handle specific string-based serialization formats. ```go package main import ( "fmt" "github.com/BurntSushi/toml" "strconv" ) // TypedValue can be marshaled/unmarshaled with validation type TypedValue struct { IntVal int StrVal string } func (tv TypedValue) MarshalTOML() ([]byte, error) { // Encode as "int:string" format return []byte(fmt.Sprintf(`"%d:%s"`, tv.IntVal, tv.StrVal)), nil } func (tv *TypedValue) UnmarshalTOML(v any) error { str, ok := v.(string) if !ok { return fmt.Errorf("expected string, got %T", v) } // Parse "int:string" format parts := make([]string, 2) n, err := fmt.Sscanf(str, "%d:%s", &tv.IntVal, &tv.StrVal) if err != nil || n != 2 { return fmt.Errorf("invalid format: %s", str) } return nil } func main() { // Marshal tv := TypedValue{IntVal: 42, StrVal: "hello"} bytes, _ := toml.Marshal(map[string]interface{}{"value": tv}) fmt.Println(string(bytes)) // value = "42:hello" // Unmarshal var config struct { Value TypedValue } toml.Unmarshal([]byte(`value = "99:world"`), &config) fmt.Printf("Parsed: %+v\n", config.Value) } ``` -------------------------------- ### Define multiple tables with key-value pairs Source: https://github.com/burntsushi/toml/blob/master/internal/toml-test/specs/v1.1.0.md Key/value pairs follow the header until the next header or EOF. ```toml [table-1] key1 = "some string" key2 = 123 [table-2] key1 = "another string" key2 = 456 ``` -------------------------------- ### Use Structs for Configuration Source: https://github.com/burntsushi/toml/blob/master/_autodocs/performance-and-best-practices.md Prefer using defined structs over maps to ensure type safety and detect unexpected keys during decoding. ```go // Good: type-safe, validates structure type Config struct { Database DatabaseConfig Server ServerConfig } var cfg Config toml.DecodeFile("config.toml", &cfg) // Less safe: accepts any keys var cfg map[string]interface{} toml.DecodeFile("config.toml", &cfg) ``` -------------------------------- ### Parse nested database configuration in Go Source: https://github.com/burntsushi/toml/blob/master/_autodocs/complete-examples.md Shows how to map nested TOML tables to nested Go structs, including custom tag mapping for fields like max_connections. ```go package main import ( "fmt" "github.com/BurntSushi/toml" "time" ) type DatabaseConfig struct { Host string Port int Username string Password string Database string MaxConnections int `toml:"max_connections"` ConnectTimeout time.Duration `toml:"connect_timeout"` IdleTimeout time.Duration `toml:"idle_timeout"` SSL bool } type Config struct { AppName string Database DatabaseConfig } func main() { tomlData := ` app_name = "DataService" [database] host = "localhost" port = 5432 username = "postgres" password = "secret" database = "mydb" max_connections = 20 connect_timeout = "5s" idle_timeout = "10m" ssl = true ` var cfg Config toml.Unmarshal([]byte(tomlData), &cfg) fmt.Printf("Connecting to %s:%d as %s\n", cfg.Database.Host, cfg.Database.Port, cfg.Database.Username, ) fmt.Printf("Max connections: %d\n", cfg.Database.MaxConnections) fmt.Printf("Timeouts: conn=%v, idle=%v\n", cfg.Database.ConnectTimeout, cfg.Database.IdleTimeout, ) } ``` -------------------------------- ### Define Struct Tags Source: https://github.com/burntsushi/toml/blob/master/_autodocs/struct-field-mapping.md Illustrates the syntax for using toml struct tags to define custom keys and apply encoding options. ```go type Example struct { Field string `toml:"custom_key"` Field string `toml:"custom_key,omitempty"` Field string `toml:"custom_key,omitzero"` Field string `toml:"-"` } ``` -------------------------------- ### Table ordering recommendations Source: https://github.com/burntsushi/toml/blob/master/internal/toml-test/specs/v1.1.0.md Defining tables out-of-order is discouraged. ```toml # VALID BUT DISCOURAGED [fruit.apple] [animal] [fruit.orange] ``` ```toml # RECOMMENDED [fruit.apple] [fruit.orange] [animal] ``` -------------------------------- ### Validate Configuration with MetaData Source: https://github.com/burntsushi/toml/blob/master/_autodocs/metadata-api.md Uses MetaData methods to ensure required keys exist and reject unexpected keys in a TOML configuration. ```go package main import ( "fmt" "github.com/BurntSushi/toml" ) type AppConfig struct { Name string Port int } func loadConfig(tomlData string) error { var cfg AppConfig md, err := toml.Decode(tomlData, &cfg) if err != nil { return fmt.Errorf("parse error: %w", err) } // Ensure all expected keys exist requiredKeys := [][]string{ {"name"}, {"port"}, } for _, k := range requiredKeys { if !md.IsDefined(k...) { return fmt.Errorf("missing required key: %s", toml.Key(k).String()) } } // Reject unexpected keys if len(md.Undecoded()) > 0 { return fmt.Errorf("unexpected keys: %v", md.Undecoded()) } return nil } func main() { tomlData := `name = "app" port = 8080` if err := loadConfig(tomlData); err != nil { fmt.Println("Error:", err) return } fmt.Println("Config valid") } ``` -------------------------------- ### Dotted Keys as Floats Source: https://github.com/burntsushi/toml/blob/master/internal/toml-test/specs/v1.0.0.md Demonstrates how dotted keys can be misinterpreted as floats, which is generally discouraged. ```toml 3.14159 = "pi" ``` ```json { "3": { "14159": "pi" } } ``` -------------------------------- ### List all keys with Keys Source: https://github.com/burntsushi/toml/blob/master/_autodocs/metadata-api.md The Keys method returns a slice of all keys present in the document, maintaining the order in which they appeared in the source. ```go package main import ( "fmt" "github.com/BurntSushi/toml" ) func main() { tomlData := ` name = "Alice" age = 30 [address] street = "123 Main St" city = "Portland" [[servers]] name = "web1" [[servers]] name = "web2" ` var data map[string]interface{} md, _ := toml.Decode(tomlData, &data) for _, k := range md.Keys() { fmt.Printf("Key: %v, Type: %s\n", k, md.Type(k...)) } // Output: // Key: [name], Type: String // Key: [age], Type: Integer // Key: [address], Type: Hash // Key: [address street], Type: String // Key: [address city], Type: String // Key: [servers], Type: ArrayHash // Key: [servers name], Type: String // Key: [servers name], Type: String } ``` -------------------------------- ### Configure Decoder Options Source: https://github.com/burntsushi/toml/blob/master/_autodocs/quick-reference.md Customize decoder behavior such as setting the maximum table nesting depth. ```go dec := toml.NewDecoder(reader) // Set max table nesting (default: 128) dec.MaxTableNesting(64) // Parse meta, err := dec.Decode(&cfg) ``` -------------------------------- ### Unmarshal TOML Strings to Go Types Source: https://github.com/burntsushi/toml/blob/master/_autodocs/type-conversions.md Illustrates handling basic, literal, and multi-line strings. Literal strings preserve characters exactly as written, while basic strings process escape sequences. ```go package main import ( "fmt" "github.com/BurntSushi/toml" ) type Config struct { Title string Description string Path string } func main() { tomlData := ` title = "Basic String" description = '''Literal string with newlines and \escapes are literal''' path = "C:\\Users\\Name" ` var cfg Config toml.Unmarshal([]byte(tomlData), &cfg) fmt.Println("Title:", cfg.Title) fmt.Println("Description:", cfg.Description) fmt.Println("Path:", cfg.Path) } ``` -------------------------------- ### Decoding TOML in Go Source: https://github.com/burntsushi/toml/blob/master/_autodocs/00-START-HERE.md Demonstrates three common methods for decoding TOML data into Go structures: unmarshaling from a string, decoding from a file, and streaming from an io.Reader. ```go // 1. Simple: decode TOML string var cfg Config toml.Unmarshal(data, &cfg) // 2. Files: load from file toml.DecodeFile("config.toml", &cfg) // 3. Streaming: from io.Reader dec := toml.NewDecoder(reader) dec.Decode(&cfg) ``` -------------------------------- ### Import the TOML library Source: https://github.com/burntsushi/toml/blob/master/_autodocs/quick-reference.md Required import statement for accessing the library functionality. ```go import "github.com/BurntSushi/toml" ``` -------------------------------- ### Perform Case-Insensitive Field Matching Source: https://github.com/burntsushi/toml/blob/master/_autodocs/struct-field-mapping.md Demonstrates how fields are matched case-insensitively when no exact match is found. Note that keys must still match the field name structure without underscore handling. ```go package main import ( "fmt" "github.com/BurntSushi/toml" ) type Config struct { DatabaseHost string // Field name in PascalCase DebugMode bool } func main() { // TOML uses snake_case, but field names are PascalCase tomlData := ` database_host = "localhost" debug_mode = true ` var cfg Config md, _ := toml.Decode(tomlData, &cfg) fmt.Println("Host:", cfg.DatabaseHost) // "localhost" fmt.Println("Debug:", cfg.DebugMode) // true // Note: This matching is case-insensitive but keys must still match // "databasehost" != "database_host" (no underscore handling) } ``` -------------------------------- ### Validate Configuration Strictly Source: https://github.com/burntsushi/toml/blob/master/_autodocs/README.md Check for undecoded keys after decoding to ensure the TOML matches the expected structure. ```go md, _ := toml.Decode(tomlData, &cfg) if undecoded := md.Undecoded(); len(undecoded) > 0 { return fmt.Errorf("unexpected keys: %v", undecoded) } ``` -------------------------------- ### Define tables with headers and sub-tables Source: https://github.com/burntsushi/toml/blob/master/internal/toml-test/specs/v1.0.0.md Shows the use of table headers and adding sub-tables to existing structures. ```toml [fruit] apple.color = "red" apple.taste.sweet = true # [fruit.apple] # INVALID # [fruit.apple.taste] # INVALID [fruit.apple.texture] # you can add sub-tables smooth = true ``` -------------------------------- ### Inline Table Usage Source: https://github.com/burntsushi/toml/blob/master/internal/toml-test/specs/v1.0.0.md Shows how to define arrays of inline tables for concise data representation. ```toml points = [ { x = 1, y = 2, z = 3 }, { x = 7, y = 8, z = 9 }, { x = 2, y = 4, z = 8 } ] ``` -------------------------------- ### Unmarshal TOML Arrays to Go Slices and Arrays Source: https://github.com/burntsushi/toml/blob/master/_autodocs/type-conversions.md Shows how to map TOML arrays into Go slices or fixed-size arrays. ```go package main import ( "fmt" "github.com/BurntSushi/toml" ) type Config struct { Numbers []int Names []string Binary [3]bool FloatArray []float64 } func main() { tomlData := ` numbers = [1, 2, 3, 4, 5] names = ["Alice", "Bob", "Charlie"] binary = [true, false, true] float_array = [1.1, 2.2, 3.3] ` var cfg Config toml.Unmarshal([]byte(tomlData), &cfg) fmt.Printf("Numbers: %v\n", cfg.Numbers) fmt.Printf("Names: %v\n", cfg.Names) fmt.Printf("Binary: %v\n", cfg.Binary) fmt.Printf("Floats: %v\n", cfg.FloatArray) } ``` -------------------------------- ### ErrorWithUsage() Source: https://github.com/burntsushi/toml/blob/master/_autodocs/error-handling.md Returns the most detailed error format including usage guidance. ```APIDOC ## func (pe ParseError) ErrorWithUsage() string ### Description Returns the output of ErrorWithPosition plus additional usage guidance if available. This is the most detailed error format provided. ``` -------------------------------- ### Define struct tags Source: https://github.com/burntsushi/toml/blob/master/_autodocs/quick-reference.md Mapping struct fields to TOML keys and configuring serialization behavior. ```go type Config struct { Name string `toml:"name"` CustomKey string `toml:"custom_name"` Optional string `toml:"optional,omitempty"` ZeroSkip int `toml:"count,omitzero"` NotSaved string `toml:"-"` } ``` -------------------------------- ### Displaying error context with usage guidance in Go Source: https://github.com/burntsushi/toml/blob/master/_autodocs/error-handling.md Use ErrorWithUsage() to retrieve the most detailed error report, including position context and helpful usage guidance. ```go package main import ( "fmt" "github.com/BurntSushi/toml" ) func main() { invalidTOML := `x = [{ key = 42 # comment` var config map[string]interface{} err := toml.Unmarshal([]byte(invalidTOML), &config) if err != nil { pe := err.(toml.ParseError) fmt.Println(pe.ErrorWithUsage()) // Shows error with position and guidance text } } ``` -------------------------------- ### Perform metadata operations Source: https://github.com/burntsushi/toml/blob/master/_autodocs/quick-reference.md Inspecting decoded data for key existence, types, and unused keys. ```go meta, _ := toml.Decode(data, &cfg) // Check key existence if meta.IsDefined("section", "key") { // Key exists } // Get TOML type typeStr := meta.Type("section", "key") // "String", "Integer", "Hash", etc. // List all keys for _, key := range meta.Keys() { fmt.Println(key.String()) // "a.b.c" } // Find unused keys for _, key := range meta.Undecoded() { fmt.Printf("Not mapped: %s\n", key.String()) } // Decode primitive value later var value string meta.PrimitiveDecode(cfg.SomePrimitive, &value) ``` -------------------------------- ### Float with Underscores Source: https://github.com/burntsushi/toml/blob/master/internal/toml-test/specs/v1.1.0.md Demonstrates the use of underscores for readability in float values. ```toml flt8 = 224_617.445_991_228 ``` -------------------------------- ### Key.String() Source: https://github.com/burntsushi/toml/blob/master/_autodocs/metadata-api.md Returns the string representation of a TOML key path, applying proper quoting and escaping for special characters. ```APIDOC ## func (k Key) String() string ### Description Returns the string representation of the key, properly quoted if necessary. Bare keys are unquoted, while keys with special characters are double-quoted with escaping. ### Signature `func (k Key) String() string` ### Example ```go k1 := toml.Key{"simple"} fmt.Println(k1.String()) // "simple" k2 := toml.Key{"with space"} fmt.Println(k2.String()) // "\"with space\"" ``` ``` -------------------------------- ### Validate Configuration Keys Source: https://github.com/burntsushi/toml/blob/master/_autodocs/00-START-HERE.md Uses the MetaData API to check for keys in the TOML data that were not mapped to the struct. Helps identify typos or deprecated configuration settings. ```go meta, _ := toml.Decode(data, &cfg) if undecoded := meta.Undecoded(); len(undecoded) > 0 { return fmt.Errorf("unexpected keys: %v", undecoded) } ``` -------------------------------- ### Implement Strict Decoding Source: https://github.com/burntsushi/toml/blob/master/_autodocs/quick-reference.md Check for unknown keys in the TOML data by inspecting the metadata returned by the decoder. ```go meta, err := toml.Decode(data, &cfg) if err != nil { return err } if len(meta.Undecoded()) > 0 { return fmt.Errorf("unknown keys: %v", meta.Undecoded()) } ``` -------------------------------- ### Manage large data efficiently Source: https://github.com/burntsushi/toml/blob/master/_autodocs/performance-and-best-practices.md Avoid loading large files into memory via toml.Primitive; store file paths and process data in chunks instead. ```go // Wrong: type Config struct { DataFile toml.Primitive // Entire 100MB file as Primitive } // Later: decode entire file into memory ``` ```go // Right: // Store filename, load data separately when needed type Config struct { DataFile string // File path } // Load file only when needed, process in chunks ``` -------------------------------- ### Inspect TOML key types Source: https://github.com/burntsushi/toml/blob/master/cmd/tomlv/README.md Display the inferred types for every key within a TOML file. ```bash $ tomlv -types some-toml-file.toml ``` -------------------------------- ### Configure TOML Encoder Source: https://github.com/burntsushi/toml/blob/master/_autodocs/quick-reference.md Customize encoder settings such as indentation before encoding data. ```go enc := toml.NewEncoder(writer) // Customize indentation (default: " " two spaces) enc.Indent = "\t" // Encode err := enc.Encode(cfg) // flush is automatic with Close (if implements it) ``` -------------------------------- ### Define a basic table Source: https://github.com/burntsushi/toml/blob/master/internal/toml-test/specs/v1.1.0.md Tables are defined by headers on their own line. ```toml [table] ``` -------------------------------- ### Unmarshal TOML Datetimes to time.Time Source: https://github.com/burntsushi/toml/blob/master/_autodocs/type-conversions.md Demonstrates mapping various TOML datetime formats into Go time.Time struct fields. ```go package main import ( "fmt" "github.com/BurntSushi/toml" "time" ) type Config struct { Created time.Time Modified time.Time LaunchDate time.Time Startup time.Time } func main() { tomlData := ` created = 2024-01-15T10:30:00Z modified = 2024-01-15T10:30:00-05:00 launch_date = 2024-01-15 startup = 10:30:00 ` var cfg Config toml.Unmarshal([]byte(tomlData), &cfg) fmt.Printf("Created: %v\n", cfg.Created) fmt.Printf("Modified: %v\n", cfg.Modified) fmt.Printf("Launch: %v\n", cfg.LaunchDate) fmt.Printf("Startup: %v\n", cfg.Startup) } ``` -------------------------------- ### Perform Runtime Type Inspection Source: https://github.com/burntsushi/toml/blob/master/_autodocs/quick-reference.md Use the metadata object to verify the TOML type of a specific key before processing. ```go meta, _ := toml.Decode(data, &cfg) if meta.Type("section", "key") == "Hash" { // It's a table, not a string } ``` -------------------------------- ### Use omitempty Tag Option Source: https://github.com/burntsushi/toml/blob/master/_autodocs/struct-field-mapping.md Demonstrates how the omitempty option skips fields with empty values during encoding. ```go package main import ( "fmt" "github.com/BurntSushi/toml" ) type Person struct { Name string `toml:"name"` Email string `toml:"email,omitempty"` Tags []string `toml:"tags,omitempty"` Description string `toml:"description,omitempty"` } func main() { // Fields with empty values will be omitted when encoding person := Person{ Name: "Alice", Email: "", // Empty string: omitted Tags: []string{}, // Empty slice: omitted } bytes, _ := toml.Marshal(person) fmt.Println(string(bytes)) // Output: // name = "Alice" // (email and tags omitted because empty) } ``` -------------------------------- ### Unmarshal time.Duration from TOML Source: https://github.com/burntsushi/toml/blob/master/_autodocs/type-conversions.md Demonstrates parsing TOML strings and integers into Go time.Duration fields. ```go package main import ( "fmt" "github.com/BurntSushi/toml" "time" ) type Config struct { Timeout time.Duration RetryWait time.Duration LongDuration time.Duration } func main() { tomlData := ` timeout = "30s" retry_wait = "1m30s" long_duration = 3600000000000 # 1 hour in nanoseconds ` var cfg Config toml.Unmarshal([]byte(tomlData), &cfg) fmt.Printf("Timeout: %v\n", cfg.Timeout) fmt.Printf("Retry: %v\n", cfg.RetryWait) fmt.Printf("Long: %v\n", cfg.LongDuration) } ``` -------------------------------- ### Configure MaxTableNesting Source: https://github.com/burntsushi/toml/blob/master/_autodocs/decoder.md Sets the maximum allowed table nesting depth to prevent resource exhaustion. ```go func (dec *Decoder) MaxTableNesting(l int) ``` ```go dec := toml.NewDecoder(strings.NewReader(tomlData)) dec.MaxTableNesting(64) // Limit nesting to 64 levels ``` -------------------------------- ### Document Required vs. Optional Fields Source: https://github.com/burntsushi/toml/blob/master/_autodocs/performance-and-best-practices.md Use struct tags like omitempty and omitzero to clarify field requirements and handle zero values during serialization. ```go package main import "github.com/BurntSushi/toml" type Config struct { // Required fields (no omitempty) Name string Version string // Optional fields Description string `toml:"description,omitempty"` Tags []string `toml:"tags,omitempty"` // Optional with default-worthy zero value RetryCount int `toml:"retry_count,omitzero"` MaxWait int `toml:"max_wait,omitzero"` EnableCache bool `toml:"-"` // Internal-only, never serialized } ``` -------------------------------- ### Decode TOML from file Source: https://github.com/burntsushi/toml/blob/master/_autodocs/encoding-functions.md Reads a TOML file from the filesystem and decodes its contents into a Go value. ```go func DecodeFile(path string, v any) (MetaData, error) ``` ```go package main import ( "fmt" "github.com/BurntSushi/toml" ) type AppConfig struct { Name string Version string Debug bool } func main() { var cfg AppConfig md, err := toml.DecodeFile("config.toml", &cfg) if err != nil { fmt.Println("Failed to load config:", err) return } fmt.Printf("Loaded: %s v%s (debug=%v)\n", cfg.Name, cfg.Version, cfg.Debug) fmt.Printf("Found %d keys in file\n", len(md.Keys())) } ``` -------------------------------- ### Unmarshal TOML Array of Tables to Go Slices Source: https://github.com/burntsushi/toml/blob/master/_autodocs/type-conversions.md Demonstrates mapping TOML array of tables syntax into a slice of structs. ```go package main import ( "fmt" "github.com/BurntSushi/toml" ) type Server struct { Name string Addr string } type Config struct { Servers []Server } func main() { tomlData := ` [[servers]] name = "web1" addr = "192.168.1.1" [[servers]] name = "web2" addr = "192.168.1.2" ` var cfg Config toml.Unmarshal([]byte(tomlData), &cfg) for _, s := range cfg.Servers { fmt.Printf("%s: %s\n", s.Name, s.Addr) } } ``` -------------------------------- ### Use struct tags for custom mapping Source: https://github.com/burntsushi/toml/blob/master/README.md Use the `toml` struct tag to map Go fields to specific TOML keys. ```toml some_key_NAME = "wat" ``` ```go type TOML struct { ObscureKey string `toml:"some_key_NAME"` } ``` -------------------------------- ### Use Skip Tag Source: https://github.com/burntsushi/toml/blob/master/_autodocs/struct-field-mapping.md Demonstrates how the toml:"-" tag prevents a field from being encoded or decoded. ```go package main import ( "fmt" "github.com/BurntSushi/toml" ) type User struct { Name string `toml:"name"` Password string `toml:"-"` // Never encoded/decoded Secret string `toml:"-"` // Internal use only } func main() { user := User{ Name: "alice", Password: "secret123", Secret: "internal-data", } bytes, _ := toml.Marshal(user) fmt.Println(string(bytes)) // Output: // name = "alice" // (Password and Secret are not included) } ```