Documentation
¶
Overview ¶
Package dotprop provides get/set/has/delete access to nested map[string]any structures using dotted path strings, mirroring the behavior of the npm "dot-prop" library, using only the Go standard library. It exposes four functions — Get, Has, Set, and Delete — that address a value deep inside a tree of maps and slices by a single string path such as "a.b.c" rather than by a chain of hand-written map lookups and type assertions.
This is the utility you want when working with dynamically shaped data: configuration loaded from JSON or YAML, a decoded request body, or any map[string]any whose structure is known by path rather than by a Go type. It lets a caller read config.Get(cfg, "server.tls.enabled") or set a deeply nested default without first checking that every intermediate map exists, which keeps option-merging and template-context code short and free of nil-map panics.
A path is split on unescaped dots into segments. A literal dot inside a key can be escaped with a backslash, so the Go string "a\\.b" (the path a\.b) refers to the single key "a.b" rather than to a nested a then b; a backslash itself is escaped the same way, and a trailing backslash is kept literally. At each step the resolver looks at the current node: if it is a map[string]any the segment is used as a string key, and if it is a []any the segment is parsed as a base-ten index into the slice. Numeric segments therefore index slices only when the current value actually is a slice; against a map the same digits are an ordinary string key.
The four operations have well-defined behavior on the awkward inputs. Get returns (value, true) when the whole path resolves and (nil, false) otherwise — including a missing key, an out-of-range or negative slice index, a non-numeric index into a slice, or an attempt to descend into a scalar leaf — and Has is simply Get with the value discarded. Set creates intermediate map[string]any nodes as needed and overwrites any non-map value that sits in the way of the path, then returns obj so calls can be chained; it does not create slice nodes. Delete removes the addressed key and reports whether something was actually removed. A nil obj or an empty path is a no-op: Get and Has report absence, Set returns obj unchanged, and Delete returns false.
Parity with the Node original covers the core get/set/has/delete surface and the dot-with-backslash-escape path grammar. The deliberate differences are idiomatic and reflect Go's type system: values are map[string]any and []any instead of arbitrary JavaScript objects, Get returns the Go-style (value, ok) pair rather than an optional-or-default, array indices only apply to real []any slices, and this port does not implement dot-prop's default-value argument or its escaping of bracket-style paths — paths are dot-and-backslash only.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Delete ¶
Delete removes the value at the given dotted path. It returns true if a value was present and removed, false otherwise.
func Get ¶
Get retrieves the value at the given dotted path. It returns the value and true when the path resolves, or nil and false otherwise. Numeric segments index into []any slices; all other segments are map keys.
Example ¶
ExampleGet reads a value from deep inside a tree of maps by a single dotted path. The path "a.b.c" is split on dots and each segment is used as a map key, descending one level at a time. Get returns the value and true when the whole path resolves, or nil and false otherwise, so a caller can address nested config without hand-written lookups and type assertions.
package main
import (
"fmt"
"github.com/malcolmston/express/dotprop"
)
func main() {
obj := map[string]any{
"a": map[string]any{
"b": map[string]any{"c": 42},
},
}
value, ok := dotprop.Get(obj, "a.b.c")
fmt.Println(value, ok)
}
Output: 42 true
func Has ¶
Has reports whether the given dotted path resolves to a value in obj.
Example ¶
ExampleHas reports whether a dotted path resolves to a value, without returning the value itself. It is simply Get with the value discarded. Here a present path reports true and a missing sibling reports false, which is handy for feature-flag or optional-config checks.
package main
import (
"fmt"
"github.com/malcolmston/express/dotprop"
)
func main() {
obj := map[string]any{"a": map[string]any{"b": 1}}
fmt.Println(dotprop.Has(obj, "a.b"))
fmt.Println(dotprop.Has(obj, "a.c"))
}
Output: true false
func Set ¶
Set assigns value at the given dotted path, creating intermediate map[string]any nodes as needed. It returns obj to allow chaining. If obj is nil or path is empty, obj is returned unchanged. Existing non-map intermediate values along the path are overwritten with new maps.
Example ¶
ExampleSet assigns a value at a dotted path, creating intermediate maps as needed. Starting from an empty map, setting "server.port" builds the nested "server" map automatically. Set returns the same top-level map so calls can be chained, and reading the value back confirms it was stored at the nested location.
package main
import (
"fmt"
"github.com/malcolmston/express/dotprop"
)
func main() {
obj := map[string]any{}
dotprop.Set(obj, "server.port", 8080)
value, ok := dotprop.Get(obj, "server.port")
fmt.Println(value, ok)
}
Output: 8080 true
Types ¶
This section is empty.