564 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			564 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| # go-toml v2
 | |
| 
 | |
| Go library for the [TOML](https://toml.io/en/) format.
 | |
| 
 | |
| This library supports [TOML v1.0.0](https://toml.io/en/v1.0.0).
 | |
| 
 | |
| [🐞 Bug Reports](https://github.com/pelletier/go-toml/issues)
 | |
| 
 | |
| [💬 Anything else](https://github.com/pelletier/go-toml/discussions)
 | |
| 
 | |
| ## Documentation
 | |
| 
 | |
| Full API, examples, and implementation notes are available in the Go
 | |
| documentation.
 | |
| 
 | |
| [](https://pkg.go.dev/github.com/pelletier/go-toml/v2)
 | |
| 
 | |
| ## Import
 | |
| 
 | |
| ```go
 | |
| import "github.com/pelletier/go-toml/v2"
 | |
| ```
 | |
| 
 | |
| See [Modules](#Modules).
 | |
| 
 | |
| ## Features
 | |
| 
 | |
| ### Stdlib behavior
 | |
| 
 | |
| As much as possible, this library is designed to behave similarly as the
 | |
| standard library's `encoding/json`.
 | |
| 
 | |
| ### Performance
 | |
| 
 | |
| While go-toml favors usability, it is written with performance in mind. Most
 | |
| operations should not be shockingly slow. See [benchmarks](#benchmarks).
 | |
| 
 | |
| ### Strict mode
 | |
| 
 | |
| `Decoder` can be set to "strict mode", which makes it error when some parts of
 | |
| the TOML document was not present in the target structure. This is a great way
 | |
| to check for typos. [See example in the documentation][strict].
 | |
| 
 | |
| [strict]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#example-Decoder.DisallowUnknownFields
 | |
| 
 | |
| ### Contextualized errors
 | |
| 
 | |
| When most decoding errors occur, go-toml returns [`DecodeError`][decode-err]),
 | |
| which contains a human readable contextualized version of the error. For
 | |
| example:
 | |
| 
 | |
| ```
 | |
| 2| key1 = "value1"
 | |
| 3| key2 = "missing2"
 | |
|  | ~~~~ missing field
 | |
| 4| key3 = "missing3"
 | |
| 5| key4 = "value4"
 | |
| ```
 | |
| 
 | |
| [decode-err]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#DecodeError
 | |
| 
 | |
| ### Local date and time support
 | |
| 
 | |
| TOML supports native [local date/times][ldt]. It allows to represent a given
 | |
| date, time, or date-time without relation to a timezone or offset. To support
 | |
| this use-case, go-toml provides [`LocalDate`][tld], [`LocalTime`][tlt], and
 | |
| [`LocalDateTime`][tldt]. Those types can be transformed to and from `time.Time`,
 | |
| making them convenient yet unambiguous structures for their respective TOML
 | |
| representation.
 | |
| 
 | |
| [ldt]: https://toml.io/en/v1.0.0#local-date-time
 | |
| [tld]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#LocalDate
 | |
| [tlt]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#LocalTime
 | |
| [tldt]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#LocalDateTime
 | |
| 
 | |
| ## Getting started
 | |
| 
 | |
| Given the following struct, let's see how to read it and write it as TOML:
 | |
| 
 | |
| ```go
 | |
| type MyConfig struct {
 | |
|       Version int
 | |
|       Name    string
 | |
|       Tags    []string
 | |
| }
 | |
| ```
 | |
| 
 | |
| ### Unmarshaling
 | |
| 
 | |
| [`Unmarshal`][unmarshal] reads a TOML document and fills a Go structure with its
 | |
| content. For example:
 | |
| 
 | |
| ```go
 | |
| doc := `
 | |
| version = 2
 | |
| name = "go-toml"
 | |
| tags = ["go", "toml"]
 | |
| `
 | |
| 
 | |
| var cfg MyConfig
 | |
| err := toml.Unmarshal([]byte(doc), &cfg)
 | |
| if err != nil {
 | |
|       panic(err)
 | |
| }
 | |
| fmt.Println("version:", cfg.Version)
 | |
| fmt.Println("name:", cfg.Name)
 | |
| fmt.Println("tags:", cfg.Tags)
 | |
| 
 | |
| // Output:
 | |
| // version: 2
 | |
| // name: go-toml
 | |
| // tags: [go toml]
 | |
| ```
 | |
| 
 | |
| [unmarshal]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#Unmarshal
 | |
| 
 | |
| ### Marshaling
 | |
| 
 | |
| [`Marshal`][marshal] is the opposite of Unmarshal: it represents a Go structure
 | |
| as a TOML document:
 | |
| 
 | |
| ```go
 | |
| cfg := MyConfig{
 | |
|       Version: 2,
 | |
|       Name:    "go-toml",
 | |
|       Tags:    []string{"go", "toml"},
 | |
| }
 | |
| 
 | |
| b, err := toml.Marshal(cfg)
 | |
| if err != nil {
 | |
|       panic(err)
 | |
| }
 | |
| fmt.Println(string(b))
 | |
| 
 | |
| // Output:
 | |
| // Version = 2
 | |
| // Name = 'go-toml'
 | |
| // Tags = ['go', 'toml']
 | |
| ```
 | |
| 
 | |
| [marshal]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#Marshal
 | |
| 
 | |
| ## Unstable API
 | |
| 
 | |
| This API does not yet follow the backward compatibility guarantees of this
 | |
| library. They provide early access to features that may have rough edges or an
 | |
| API subject to change.
 | |
| 
 | |
| ### Parser
 | |
| 
 | |
| Parser is the unstable API that allows iterative parsing of a TOML document at
 | |
| the AST level. See https://pkg.go.dev/github.com/pelletier/go-toml/v2/unstable.
 | |
| 
 | |
| ## Benchmarks
 | |
| 
 | |
| Execution time speedup compared to other Go TOML libraries:
 | |
| 
 | |
| <table>
 | |
|     <thead>
 | |
|         <tr><th>Benchmark</th><th>go-toml v1</th><th>BurntSushi/toml</th></tr>
 | |
|     </thead>
 | |
|     <tbody>
 | |
|         <tr><td>Marshal/HugoFrontMatter-2</td><td>1.9x</td><td>1.9x</td></tr>
 | |
|         <tr><td>Marshal/ReferenceFile/map-2</td><td>1.7x</td><td>1.8x</td></tr>
 | |
|         <tr><td>Marshal/ReferenceFile/struct-2</td><td>2.2x</td><td>2.5x</td></tr>
 | |
|         <tr><td>Unmarshal/HugoFrontMatter-2</td><td>2.9x</td><td>2.9x</td></tr>
 | |
|         <tr><td>Unmarshal/ReferenceFile/map-2</td><td>2.6x</td><td>2.9x</td></tr>
 | |
|         <tr><td>Unmarshal/ReferenceFile/struct-2</td><td>4.4x</td><td>5.3x</td></tr>
 | |
|      </tbody>
 | |
| </table>
 | |
| <details><summary>See more</summary>
 | |
| <p>The table above has the results of the most common use-cases. The table below
 | |
| contains the results of all benchmarks, including unrealistic ones. It is
 | |
| provided for completeness.</p>
 | |
| 
 | |
| <table>
 | |
|     <thead>
 | |
|         <tr><th>Benchmark</th><th>go-toml v1</th><th>BurntSushi/toml</th></tr>
 | |
|     </thead>
 | |
|     <tbody>
 | |
|         <tr><td>Marshal/SimpleDocument/map-2</td><td>1.8x</td><td>2.9x</td></tr>
 | |
|         <tr><td>Marshal/SimpleDocument/struct-2</td><td>2.7x</td><td>4.2x</td></tr>
 | |
|         <tr><td>Unmarshal/SimpleDocument/map-2</td><td>4.5x</td><td>3.1x</td></tr>
 | |
|         <tr><td>Unmarshal/SimpleDocument/struct-2</td><td>6.2x</td><td>3.9x</td></tr>
 | |
|         <tr><td>UnmarshalDataset/example-2</td><td>3.1x</td><td>3.5x</td></tr>
 | |
|         <tr><td>UnmarshalDataset/code-2</td><td>2.3x</td><td>3.1x</td></tr>
 | |
|         <tr><td>UnmarshalDataset/twitter-2</td><td>2.5x</td><td>2.6x</td></tr>
 | |
|         <tr><td>UnmarshalDataset/citm_catalog-2</td><td>2.1x</td><td>2.2x</td></tr>
 | |
|         <tr><td>UnmarshalDataset/canada-2</td><td>1.6x</td><td>1.3x</td></tr>
 | |
|         <tr><td>UnmarshalDataset/config-2</td><td>4.3x</td><td>3.2x</td></tr>
 | |
|         <tr><td>[Geo mean]</td><td>2.7x</td><td>2.8x</td></tr>
 | |
|      </tbody>
 | |
| </table>
 | |
| <p>This table can be generated with <code>./ci.sh benchmark -a -html</code>.</p>
 | |
| </details>
 | |
| 
 | |
| ## Modules
 | |
| 
 | |
| go-toml uses Go's standard modules system.
 | |
| 
 | |
| Installation instructions:
 | |
| 
 | |
| - Go ≥ 1.16: Nothing to do. Use the import in your code. The `go` command deals
 | |
|   with it automatically.
 | |
| - Go ≥ 1.13: `GO111MODULE=on go get github.com/pelletier/go-toml/v2`.
 | |
| 
 | |
| In case of trouble: [Go Modules FAQ][mod-faq].
 | |
| 
 | |
| [mod-faq]: https://github.com/golang/go/wiki/Modules#why-does-installing-a-tool-via-go-get-fail-with-error-cannot-find-main-module
 | |
| 
 | |
| ## Tools
 | |
| 
 | |
| Go-toml provides three handy command line tools:
 | |
| 
 | |
|  * `tomljson`: Reads a TOML file and outputs its JSON representation.
 | |
| 
 | |
|     ```
 | |
|     $ go install github.com/pelletier/go-toml/v2/cmd/tomljson@latest
 | |
|     $ tomljson --help
 | |
|     ```
 | |
| 
 | |
|  * `jsontoml`: Reads a JSON file and outputs a TOML representation.
 | |
| 
 | |
|     ```
 | |
|     $ go install github.com/pelletier/go-toml/v2/cmd/jsontoml@latest
 | |
|     $ jsontoml --help
 | |
|     ```
 | |
| 
 | |
|  * `tomll`: Lints and reformats a TOML file.
 | |
| 
 | |
|     ```
 | |
|     $ go install github.com/pelletier/go-toml/v2/cmd/tomll@latest
 | |
|     $ tomll --help
 | |
|     ```
 | |
| 
 | |
| ### Docker image
 | |
| 
 | |
| Those tools are also available as a [Docker image][docker]. For example, to use
 | |
| `tomljson`:
 | |
| 
 | |
| ```
 | |
| docker run -i ghcr.io/pelletier/go-toml:v2 tomljson < example.toml
 | |
| ```
 | |
| 
 | |
| Multiple versions are availble on [ghcr.io][docker].
 | |
| 
 | |
| [docker]: https://github.com/pelletier/go-toml/pkgs/container/go-toml
 | |
| 
 | |
| ## Migrating from v1
 | |
| 
 | |
| This section describes the differences between v1 and v2, with some pointers on
 | |
| how to get the original behavior when possible.
 | |
| 
 | |
| ### Decoding / Unmarshal
 | |
| 
 | |
| #### Automatic field name guessing
 | |
| 
 | |
| When unmarshaling to a struct, if a key in the TOML document does not exactly
 | |
| match the name of a struct field or any of the `toml`-tagged field, v1 tries
 | |
| multiple variations of the key ([code][v1-keys]).
 | |
| 
 | |
| V2 instead does a case-insensitive matching, like `encoding/json`.
 | |
| 
 | |
| This could impact you if you are relying on casing to differentiate two fields,
 | |
| and one of them is a not using the `toml` struct tag. The recommended solution
 | |
| is to be specific about tag names for those fields using the `toml` struct tag.
 | |
| 
 | |
| [v1-keys]: https://github.com/pelletier/go-toml/blob/a2e52561804c6cd9392ebf0048ca64fe4af67a43/marshal.go#L775-L781
 | |
| 
 | |
| #### Ignore preexisting value in interface
 | |
| 
 | |
| When decoding into a non-nil `interface{}`, go-toml v1 uses the type of the
 | |
| element in the interface to decode the object. For example:
 | |
| 
 | |
| ```go
 | |
| type inner struct {
 | |
|   B interface{}
 | |
| }
 | |
| type doc struct {
 | |
|   A interface{}
 | |
| }
 | |
| 
 | |
| d := doc{
 | |
|   A: inner{
 | |
|     B: "Before",
 | |
|   },
 | |
| }
 | |
| 
 | |
| data := `
 | |
| [A]
 | |
| B = "After"
 | |
| `
 | |
| 
 | |
| toml.Unmarshal([]byte(data), &d)
 | |
| fmt.Printf("toml v1: %#v\n", d)
 | |
| 
 | |
| // toml v1: main.doc{A:main.inner{B:"After"}}
 | |
| ```
 | |
| 
 | |
| In this case, field `A` is of type `interface{}`, containing a `inner` struct.
 | |
| V1 sees that type and uses it when decoding the object.
 | |
| 
 | |
| When decoding an object into an `interface{}`, V2 instead disregards whatever
 | |
| value the `interface{}` may contain and replaces it with a
 | |
| `map[string]interface{}`. With the same data structure as above, here is what
 | |
| the result looks like:
 | |
| 
 | |
| ```go
 | |
| toml.Unmarshal([]byte(data), &d)
 | |
| fmt.Printf("toml v2: %#v\n", d)
 | |
| 
 | |
| // toml v2: main.doc{A:map[string]interface {}{"B":"After"}}
 | |
| ```
 | |
| 
 | |
| This is to match `encoding/json`'s behavior. There is no way to make the v2
 | |
| decoder behave like v1.
 | |
| 
 | |
| #### Values out of array bounds ignored
 | |
| 
 | |
| When decoding into an array, v1 returns an error when the number of elements
 | |
| contained in the doc is superior to the capacity of the array. For example:
 | |
| 
 | |
| ```go
 | |
| type doc struct {
 | |
|   A [2]string
 | |
| }
 | |
| d := doc{}
 | |
| err := toml.Unmarshal([]byte(`A = ["one", "two", "many"]`), &d)
 | |
| fmt.Println(err)
 | |
| 
 | |
| // (1, 1): unmarshal: TOML array length (3) exceeds destination array length (2)
 | |
| ```
 | |
| 
 | |
| In the same situation, v2 ignores the last value:
 | |
| 
 | |
| ```go
 | |
| err := toml.Unmarshal([]byte(`A = ["one", "two", "many"]`), &d)
 | |
| fmt.Println("err:", err, "d:", d)
 | |
| // err: <nil> d: {[one two]}
 | |
| ```
 | |
| 
 | |
| This is to match `encoding/json`'s behavior. There is no way to make the v2
 | |
| decoder behave like v1.
 | |
| 
 | |
| #### Support for `toml.Unmarshaler` has been dropped
 | |
| 
 | |
| This method was not widely used, poorly defined, and added a lot of complexity.
 | |
| A similar effect can be achieved by implementing the `encoding.TextUnmarshaler`
 | |
| interface and use strings.
 | |
| 
 | |
| #### Support for `default` struct tag has been dropped
 | |
| 
 | |
| This feature adds complexity and a poorly defined API for an effect that can be
 | |
| accomplished outside of the library.
 | |
| 
 | |
| It does not seem like other format parsers in Go support that feature (the
 | |
| project referenced in the original ticket #202 has not been updated since 2017).
 | |
| Given that go-toml v2 should not touch values not in the document, the same
 | |
| effect can be achieved by pre-filling the struct with defaults (libraries like
 | |
| [go-defaults][go-defaults] can help). Also, string representation is not well
 | |
| defined for all types: it creates issues like #278.
 | |
| 
 | |
| The recommended replacement is pre-filling the struct before unmarshaling.
 | |
| 
 | |
| [go-defaults]: https://github.com/mcuadros/go-defaults
 | |
| 
 | |
| #### `toml.Tree` replacement
 | |
| 
 | |
| This structure was the initial attempt at providing a document model for
 | |
| go-toml. It allows manipulating the structure of any document, encoding and
 | |
| decoding from their TOML representation. While a more robust feature was
 | |
| initially planned in go-toml v2, this has been ultimately [removed from
 | |
| scope][nodoc] of this library, with no plan to add it back at the moment. The
 | |
| closest equivalent at the moment would be to unmarshal into an `interface{}` and
 | |
| use type assertions and/or reflection to manipulate the arbitrary
 | |
| structure. However this would fall short of providing all of the TOML features
 | |
| such as adding comments and be specific about whitespace.
 | |
| 
 | |
| 
 | |
| #### `toml.Position` are not retrievable anymore
 | |
| 
 | |
| The API for retrieving the position (line, column) of a specific TOML element do
 | |
| not exist anymore. This was done to minimize the amount of concepts introduced
 | |
| by the library (query path), and avoid the performance hit related to storing
 | |
| positions in the absence of a document model, for a feature that seemed to have
 | |
| little use. Errors however have gained more detailed position
 | |
| information. Position retrieval seems better fitted for a document model, which
 | |
| has been [removed from the scope][nodoc] of go-toml v2 at the moment.
 | |
| 
 | |
| ### Encoding / Marshal
 | |
| 
 | |
| #### Default struct fields order
 | |
| 
 | |
| V1 emits struct fields order alphabetically by default. V2 struct fields are
 | |
| emitted in order they are defined. For example:
 | |
| 
 | |
| ```go
 | |
| type S struct {
 | |
| 	B string
 | |
| 	A string
 | |
| }
 | |
| 
 | |
| data := S{
 | |
| 	B: "B",
 | |
| 	A: "A",
 | |
| }
 | |
| 
 | |
| b, _ := tomlv1.Marshal(data)
 | |
| fmt.Println("v1:\n" + string(b))
 | |
| 
 | |
| b, _ = tomlv2.Marshal(data)
 | |
| fmt.Println("v2:\n" + string(b))
 | |
| 
 | |
| // Output:
 | |
| // v1:
 | |
| // A = "A"
 | |
| // B = "B"
 | |
| 
 | |
| // v2:
 | |
| // B = 'B'
 | |
| // A = 'A'
 | |
| ```
 | |
| 
 | |
| There is no way to make v2 encoder behave like v1. A workaround could be to
 | |
| manually sort the fields alphabetically in the struct definition, or generate
 | |
| struct types using `reflect.StructOf`.
 | |
| 
 | |
| #### No indentation by default
 | |
| 
 | |
| V1 automatically indents content of tables by default. V2 does not. However the
 | |
| same behavior can be obtained using [`Encoder.SetIndentTables`][sit]. For example:
 | |
| 
 | |
| ```go
 | |
| data := map[string]interface{}{
 | |
| 	"table": map[string]string{
 | |
| 		"key": "value",
 | |
| 	},
 | |
| }
 | |
| 
 | |
| b, _ := tomlv1.Marshal(data)
 | |
| fmt.Println("v1:\n" + string(b))
 | |
| 
 | |
| b, _ = tomlv2.Marshal(data)
 | |
| fmt.Println("v2:\n" + string(b))
 | |
| 
 | |
| buf := bytes.Buffer{}
 | |
| enc := tomlv2.NewEncoder(&buf)
 | |
| enc.SetIndentTables(true)
 | |
| enc.Encode(data)
 | |
| fmt.Println("v2 Encoder:\n" + string(buf.Bytes()))
 | |
| 
 | |
| // Output:
 | |
| // v1:
 | |
| //
 | |
| // [table]
 | |
| //   key = "value"
 | |
| //
 | |
| // v2:
 | |
| // [table]
 | |
| // key = 'value'
 | |
| //
 | |
| //
 | |
| // v2 Encoder:
 | |
| // [table]
 | |
| //   key = 'value'
 | |
| ```
 | |
| 
 | |
| [sit]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#Encoder.SetIndentTables
 | |
| 
 | |
| #### Keys and strings are single quoted
 | |
| 
 | |
| V1 always uses double quotes (`"`) around strings and keys that cannot be
 | |
| represented bare (unquoted). V2 uses single quotes instead by default (`'`),
 | |
| unless a character cannot be represented, then falls back to double quotes. As a
 | |
| result of this change, `Encoder.QuoteMapKeys` has been removed, as it is not
 | |
| useful anymore.
 | |
| 
 | |
| There is no way to make v2 encoder behave like v1.
 | |
| 
 | |
| #### `TextMarshaler` emits as a string, not TOML
 | |
| 
 | |
| Types that implement [`encoding.TextMarshaler`][tm] can emit arbitrary TOML in
 | |
| v1. The encoder would append the result to the output directly. In v2 the result
 | |
| is wrapped in a string. As a result, this interface cannot be implemented by the
 | |
| root object.
 | |
| 
 | |
| There is no way to make v2 encoder behave like v1.
 | |
| 
 | |
| [tm]: https://golang.org/pkg/encoding/#TextMarshaler
 | |
| 
 | |
| #### `Encoder.CompactComments` has been removed
 | |
| 
 | |
| Emitting compact comments is now the default behavior of go-toml. This option
 | |
| is not necessary anymore.
 | |
| 
 | |
| #### Struct tags have been merged
 | |
| 
 | |
| V1 used to provide multiple struct tags: `comment`, `commented`, `multiline`,
 | |
| `toml`, and `omitempty`. To behave more like the standard library, v2 has merged
 | |
| `toml`, `multiline`, and `omitempty`. For example:
 | |
| 
 | |
| ```go
 | |
| type doc struct {
 | |
| 	// v1
 | |
| 	F string `toml:"field" multiline:"true" omitempty:"true"`
 | |
| 	// v2
 | |
| 	F string `toml:"field,multiline,omitempty"`
 | |
| }
 | |
| ```
 | |
| 
 | |
| Has a result, the `Encoder.SetTag*` methods have been removed, as there is just
 | |
| one tag now.
 | |
| 
 | |
| 
 | |
| #### `commented` tag has been removed
 | |
| 
 | |
| There is no replacement for the `commented` tag. This feature would be better
 | |
| suited in a proper document model for go-toml v2, which has been [cut from
 | |
| scope][nodoc] at the moment.
 | |
| 
 | |
| #### `Encoder.ArraysWithOneElementPerLine` has been renamed
 | |
| 
 | |
| The new name is `Encoder.SetArraysMultiline`. The behavior should be the same.
 | |
| 
 | |
| #### `Encoder.Indentation` has been renamed
 | |
| 
 | |
| The new name is `Encoder.SetIndentSymbol`. The behavior should be the same.
 | |
| 
 | |
| 
 | |
| #### Embedded structs behave like stdlib
 | |
| 
 | |
| V1 defaults to merging embedded struct fields into the embedding struct. This
 | |
| behavior was unexpected because it does not follow the standard library. To
 | |
| avoid breaking backward compatibility, the `Encoder.PromoteAnonymous` method was
 | |
| added to make the encoder behave correctly. Given backward compatibility is not
 | |
| a problem anymore, v2 does the right thing by default: it follows the behavior
 | |
| of `encoding/json`. `Encoder.PromoteAnonymous` has been removed.
 | |
| 
 | |
| [nodoc]: https://github.com/pelletier/go-toml/discussions/506#discussioncomment-1526038
 | |
| 
 | |
| ### `query`
 | |
| 
 | |
| go-toml v1 provided the [`go-toml/query`][query] package. It allowed to run
 | |
| JSONPath-style queries on TOML files. This feature is not available in v2. For a
 | |
| replacement, check out [dasel][dasel].
 | |
| 
 | |
| This package has been removed because it was essentially not supported anymore
 | |
| (last commit May 2020), increased the complexity of the code base, and more
 | |
| complete solutions exist out there.
 | |
| 
 | |
| [query]: https://github.com/pelletier/go-toml/tree/f99d6bbca119636aeafcf351ee52b3d202782627/query
 | |
| [dasel]: https://github.com/TomWright/dasel
 | |
| 
 | |
| ## Versioning
 | |
| 
 | |
| Go-toml follows [Semantic Versioning](https://semver.org). The supported version
 | |
| of [TOML](https://github.com/toml-lang/toml) is indicated at the beginning of
 | |
| this document. The last two major versions of Go are supported
 | |
| (see [Go Release Policy](https://golang.org/doc/devel/release.html#policy)).
 | |
| 
 | |
| ## License
 | |
| 
 | |
| The MIT License (MIT). Read [LICENSE](LICENSE).
 |