Documentation ¶
Overview ¶
Access nested properties in Go data structures with DAta Queries
Concepts ¶
A query result is (res any, err error)
Use assert functions or fallback functions to easily use query results with an expected type
Use As to create an assertion function from a convert function
Use Val to create a fallback function from a convert function
The convert function for target type T is func(v any) (r T, err error). If conversion of v fails, err != nil and r == nil. Otherwise, r is the conversion result.
By convention, convert functions for target type <T> are named To<T>(). Predefined assert functions are named As<T>(), predefined fallback functions <T>Or().
Use Get as the general way to perform queries. Read on to find more specific and efficient ways to query:
Index, Field, Key to step with int, string and any.
And also SliceAny, DictAny, MapAny to get query results that can be asserted from typical generic Go data.
To extend daq to your own types write convert functions and familiarize with Stepper, Slice, Dict and Map.
Convert Functions for Go's numeric types ¶
Signed and unsigned integer types are promoted to each other as long as the actual runtime value is in target type's range.
Float values are promoted to integer types if the actual float has no fraction, and it is in target type's range.
Complex values with imag() == 0 are promoted to integer by promoting the real() part according to the float rules.
Example ¶
var data any json.Unmarshal([]byte(`{ "a": 3.1415, "bs": [1, 2, 3] }`), &data) prop, _ := Get(data, "a") // Ignore error in example for brevity fmt.Println(prop) prop, err := Get(data, "b") // This will fail, no "b" fmt.Println(prop, err) x, err := AsFloat64(Get(data, "bs", 1)) // Type assertion (encoding/json uses float64 for numbers) fmt.Println(x, err) x, err = AsFloat64(Get(data, "bs", -1)) // Access backwards from end fmt.Println(x, err) x = Float64Or(-1)(Get(data, "bs", 3)) // Fallback to -1 if Get fails fmt.Println(x)
Output: 3.1415 <nil> step 0 [b]: unknown field 'b' 2 <nil> 3 <nil> -1
Index ¶
- func As[T any](conv func(any) (T, error)) func(any, error) (T, error)
- func AsBool(v any, err error) (bool, error)
- func AsDuration(v any, err error) (time.Duration, error)
- func AsFloat32(v any, err error) (float32, error)
- func AsFloat64(v any, err error) (float64, error)
- func AsInt(v any, err error) (int, error)
- func AsInt16(v any, err error) (int16, error)
- func AsInt32(v any, err error) (int32, error)
- func AsInt64(v any, err error) (int64, error)
- func AsInt8(v any, err error) (int8, error)
- func AsString(v any, err error) (string, error)
- func AsTime(v any, err error) (time.Time, error)
- func AsUint(v any, err error) (uint, error)
- func AsUint16(v any, err error) (uint16, error)
- func AsUint32(v any, err error) (uint32, error)
- func AsUint64(v any, err error) (uint64, error)
- func AsUint8(v any, err error) (uint8, error)
- func AsUintPtr(v any, err error) (uintptr, error)
- func BoolOr(fallback bool) func(any, error) bool
- func DeepEqual(lhs, rhs any) bool
- func DeepEqualFunc(lhs, rhs any, eq func(any, any) bool) bool
- func DictOr(fallback Dict) func(any, error) Dict
- func DurationOr(fallback time.Duration) func(any, error) time.Duration
- func Field(data any, name string) (res any, err error)
- func Float32Or(fallback float32) func(any, error) float32
- func Float64Or(fallback float64) func(any, error) float64
- func Get(data any, path ...any) (res any, err error)
- func Index(data any, index int) (res any, err error)
- func Int16Or(fallback int16) func(any, error) int16
- func Int32Or(fallback int32) func(any, error) int32
- func Int64Or(fallback int64) func(any, error) int64
- func Int8Or(fallback int8) func(any, error) int8
- func IntOr(fallback int) func(any, error) int
- func Key(data, key any) (res any, err error)
- func MapOr(fallback Map) func(any, error) Map
- func SliceOr(fallback Slice) func(any, error) Slice
- func Step(data, step any) (res any, err error)
- func StepEach(data any, do func(kind reflect.Kind, key, value any) error) error
- func StringOr(fallback string) func(any, error) string
- func TestingDeepEqual(t testing.TB, lhs, rhs any) (diffCount int)
- func TestingDeepEqualFunc(t testing.TB, lhs, rhs any, eq func(any, any) bool) (diffCount int)
- func TimeOr(fallback time.Time) func(any, error) time.Time
- func ToBool(v any) (bool, error)
- func ToDuration(v any) (time.Duration, error)
- func ToFloat32(v any) (float32, error)
- func ToFloat64(v any) (float64, error)
- func ToInt(v any) (int, error)
- func ToInt16(v any) (int16, error)
- func ToInt32(v any) (int32, error)
- func ToInt64(v any) (int64, error)
- func ToInt8(v any) (int8, error)
- func ToString(v any) (string, error)
- func ToTime(v any) (time.Time, error)
- func ToUint(v any) (uint, error)
- func ToUint16(v any) (uint16, error)
- func ToUint32(v any) (uint32, error)
- func ToUint64(v any) (uint64, error)
- func ToUint8(v any) (uint8, error)
- func ToUintPtr(v any) (uintptr, error)
- func Uint16Or(fallback uint16) func(any, error) uint16
- func Uint32Or(fallback uint32) func(any, error) uint32
- func Uint64Or(fallback uint64) func(any, error) uint64
- func Uint8Or(fallback uint8) func(any, error) uint8
- func UintOr(fallback uint) func(any, error) uint
- func UintPtrOr(fallback uintptr) func(any, error) uintptr
- func Val[T any](conv func(any) (T, error), fallback T) func(v any, err error) T
- type Alt
- type CollectionTypeError
- type Delta
- type Dict
- type DictAny
- type FirstIdxOf
- type FirstKeyOf
- type FirstNameOf
- type FirstOf
- type IndexOutOfRange
- type Map
- type MapAny
- type Slice
- type SliceAny
- type StepError
- type Stepper
- type Time
- type Track
- type UnknownField
- type UnknownKey
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func As ¶ added in v0.4.1
As returns the assert function for the given type conversion conv. An assert function takes any value and an error as input. If the error is nil, the assert function performs the type conversion and returns the result. Otherwise, the assert function returns T's zero value and the error. Assert functions are useful to cast query results to expected types T.
Example ¶
data := struct { Foo int Bar string }{ Foo: 4711, Bar: "baz", } fmt.Println(As(ToString)(Get(data, "Foo"))) fmt.Println(As(ToString)(Get(data, "Bar"))) fmt.Println(As(ToString)(Get(data, "void")))
Output: cannot return int as string baz <nil> step 0 [void]: unknown field 'void'
func AsBool ¶
Example ¶
fmt.Println(AsBool(Get(true))) fmt.Println(BoolOr(false)(Get(4711)))
Output: true <nil> false
func AsString ¶
Example ¶
fmt.Println(StringOr("-")(DictAny(testExample).DaQGet("a"))) fmt.Println(Val(ToString, "-")(Get(testExample, "a", 0, "d")))
Output: - foo
func Get ¶
Get queries an element res from data for a given path of steps.
Example ¶
data := map[string]any{ "a": []any{ map[string]any{ "b": map[any]any{"c": 3}, "d": "foo", }, false, }, } var i int = IntOr(-1)(Get(data, "a", 0, "b", "c")) fmt.Println(i) fmt.Println(Get(data, "a", 0, "b", "d")) fmt.Println(Get(nil, "a", 0, "b", "d"))
Output: 3 <nil> step 3 [d]: unknown field 'd' <nil> step 0 [a]: cannot step into <nil>
func StepEach ¶ added in v0.3.0
Example (Array) ¶
data := [4]any{0, '1', "two", nil} err := StepEach(data, testPrintStep) fmt.Println(err)
Output: kind 'array': key=0 / value=0 kind 'array': key=1 / value=49 kind 'array': key=2 / value="two" kind 'array': key=3 / value=<nil> <nil>
Example (Atom) ¶
err := StepEach(5180, testPrintStep) fmt.Println(err)
Output: kind 'invalid': key=<nil> / value=5180 <nil>
Example (Map) ¶
data := map[any]any{ false: "foo", 7: nil, "bar": 4711, } err := StepEach(data, testPrintStep) fmt.Println(err)
Output: kind 'map': key=false / value="foo" kind 'map': key=7 / value=<nil> kind 'map': key="bar" / value=4711 <nil>
Example (Slice) ¶
data := []any{0, '1', "two", nil} err := StepEach(data, testPrintStep) fmt.Println(err)
Output: kind 'slice': key=0 / value=0 kind 'slice': key=1 / value=49 kind 'slice': key=2 / value="two" kind 'slice': key=3 / value=<nil> <nil>
Example (Struct) ¶
type Tstnest struct { Foo int } data := struct { Tstnest Bar string Nest Tstnest }{ Tstnest: Tstnest{Foo: 4711}, Bar: "baz", Nest: Tstnest{Foo: -1}, } err := StepEach(data, testPrintStep) fmt.Println(err)
Output: kind 'struct': key="Foo" / value=4711 kind 'struct': key="Bar" / value="baz" kind 'struct': key="Nest" / value=daq.Tstnest{Foo:-1} <nil>
func TestingDeepEqual ¶ added in v0.5.0
func TestingDeepEqualFunc ¶ added in v0.5.0
func ToTime ¶ added in v0.4.1
Example ¶
t := time.Date(2023, 12, 29, 2, 4, 0, 0, time.UTC) fmt.Println(ToTime(t)) fmt.Println(ToTime(&t)) fmt.Println(ToTime((*time.Time)(nil)))
Output: 2023-12-29 02:04:00 +0000 UTC <nil> 2023-12-29 02:04:00 +0000 UTC <nil> 0001-01-01 00:00:00 +0000 UTC <nil>
func Val ¶
Val returns a fallback function for the given type conversion conv. A fallback function always returns a value of expected type T. It returns the asserted value of As in case of success. Otherwise it returns the fallback.
Example ¶
data := struct { Foo int Bar string }{ Foo: 4711, Bar: "baz", } fmt.Println(Val(ToString, "fallback1")(Get(data, "Foo"))) fmt.Println(Val(ToString, "fallback2")(Get(data, "Bar"))) fmt.Println(Val(ToString, "fallback3")(Get(data, "void")))
Output: fallback1 baz fallback3
Types ¶
type Alt ¶
Example ¶
data := []string{"foo", "bar", "baz"} fmt.Println(Step(data, "bar")) fmt.Println(Step(data, Alt{S: "bar", Or: 4711}))
Output: <nil> key lookup: cannot return []string as daq.Map 4711 <nil>
type CollectionTypeError ¶ added in v0.5.0
type CollectionTypeError struct {
// contains filtered or unexported fields
}
func (CollectionTypeError) Error ¶ added in v0.5.0
func (e CollectionTypeError) Error() string
func (CollectionTypeError) Is ¶ added in v0.5.0
func (e CollectionTypeError) Is(err error) bool
type Delta ¶ added in v0.5.0
type Dict ¶ added in v0.4.1
type Dict interface { DaQGet(name string) (res any, err error) DaQEachKey(do func(key string) error) error }
Dict is queried with a string as name.
type DictAny ¶ added in v0.4.1
func (DictAny) DaQEachKey ¶ added in v0.4.1
type FirstIdxOf ¶ added in v0.5.0
type FirstIdxOf []int
Example ¶
data := []string{"foo", "bar", "baz"} fmt.Println(Step(data, FirstIdxOf{99, 1})) // more efficient fmt.Println(Step(data, FirstOf{99, 1})) // more general
Output: bar <nil> bar <nil>
type FirstKeyOf ¶ added in v0.5.0
type FirstKeyOf []any
Example ¶
data := map[any]any{ "foo": 1, "bar": 2, "baz": 3, } fmt.Println(Step(data, FirstKeyOf{"quux", "bar"})) // more efficient fmt.Println(Step(data, FirstOf{"quux", "bar"})) // more general
Output: 2 <nil> 2 <nil>
type FirstNameOf ¶
type FirstNameOf []string
Example ¶
data := map[string]int{ "foo": 1, "bar": 2, "baz": 3, } fmt.Println(Step(data, FirstNameOf{"quux", "bar"})) // more efficient fmt.Println(Step(data, FirstOf{"quux", "bar"})) // more general
Output: 2 <nil> 2 <nil>
type IndexOutOfRange ¶ added in v0.4.1
type IndexOutOfRange struct {
I, Min, Max int
}
func (IndexOutOfRange) Error ¶ added in v0.4.1
func (e IndexOutOfRange) Error() string
type Map ¶
type Map interface { DaQGet(key any) (res any, err error) DaQEachKey(do func(key any) error) error }
Map is queried with any comparable value as key.
type Slice ¶
Slice is queried with an int index. Negative indices access from the end with -1 being the last element and -DaQLen() the first.
type Time ¶
type Time string
Example ¶
data := struct { Time string }{ Time: "2023-12-29T22:04:00Z", } // Asserting time.Time needs parsing, so we use Time() to create a parsing assertion fmt.Println(Val(Time(time.RFC3339).To, time.Time{})(Get(data, "Time"))) fmt.Println(Val(Time(time.RFC3339).To, time.Time{})(Get(data, "void")))
Output: 2023-12-29 22:04:00 +0000 UTC 0001-01-01 00:00:00 +0000 UTC
type UnknownField ¶ added in v0.4.1
type UnknownField string
func (UnknownField) Error ¶ added in v0.4.1
func (e UnknownField) Error() string
type UnknownKey ¶ added in v0.4.1
type UnknownKey struct {
// contains filtered or unexported fields
}
func (UnknownKey) Error ¶ added in v0.4.1
func (e UnknownKey) Error() string