Documentation
¶
Index ¶
- Constants
- func CopyPath(src []int) []int
- func DerefFunc(val interface{}) r.Value
- func DerefKind(val interface{}) r.Kind
- func DerefMap(val interface{}) r.Value
- func DerefPtr(val interface{}) r.Value
- func DerefSlice(val interface{}) r.Value
- func DerefStruct(val interface{}) r.Value
- func DerefType(val interface{}) r.Type
- func DerefValue(val interface{}) r.Value
- func DerefValueWithKind(src interface{}, kind r.Kind) r.Value
- func ElemType(val interface{}) r.Type
- func Fields(typ interface{}) []r.StructField
- func FuncName(val interface{}) string
- func IsColl(val interface{}) bool
- func IsEmbed(val r.StructField) bool
- func IsEmptyColl(val interface{}) bool
- func IsKindColl(kind r.Kind) bool
- func IsKindNilable(kind r.Kind) bool
- func IsNil(val interface{}) bool
- func IsPublic(pkgPath string) bool
- func IsValueEmptyColl(val r.Value) bool
- func IsValueNil(val r.Value) bool
- func IsValueZero(val r.Value) bool
- func IsZero(val interface{}) bool
- func Iter(count int) []struct{}
- func Kind(val interface{}) r.Kind
- func Len(val interface{}) int
- func NormNil(val interface{}) interface{}
- func SliceType(val interface{}) r.Type
- func TagIdent(tag string) string
- func Trawl(src, out interface{})
- func TrawlWith(src, out interface{}, fil Filter)
- func TypeDeref(typ r.Type) r.Type
- func TypeElem(typ r.Type) r.Type
- func TypeFields(typ r.Type) []r.StructField
- func TypeKind(val r.Type) r.Kind
- func ValidFunc(val interface{}) r.Value
- func ValidMap(val interface{}) r.Value
- func ValidPtr(val interface{}) r.Value
- func ValidPtrToKind(val interface{}, exp r.Kind) r.Value
- func ValidSlice(val interface{}) r.Value
- func ValidSliceOf(val interface{}, exp r.Type) r.Value
- func ValidSliceOfKind(val interface{}, exp r.Kind) r.Value
- func ValidStruct(val interface{}) r.Value
- func ValidTypeFunc(val interface{}) r.Type
- func ValidTypeMap(val interface{}) r.Type
- func ValidTypePtr(val interface{}) r.Type
- func ValidTypeSlice(val interface{}) r.Type
- func ValidTypeStruct(val interface{}) r.Type
- func ValidateFunc(val r.Value) r.Value
- func ValidateFuncIn(typ r.Type, params ...r.Type)
- func ValidateFuncNumIn(typ r.Type, exp int)
- func ValidateFuncNumOut(typ r.Type, exp int)
- func ValidateFuncOut(typ r.Type, params ...r.Type)
- func ValidateMap(val r.Value) r.Value
- func ValidatePtr(val r.Value) r.Value
- func ValidatePtrToKind(val r.Value, exp r.Kind) r.Value
- func ValidateSlice(val r.Value) r.Value
- func ValidateSliceOf(val r.Value, exp r.Type) r.Value
- func ValidateSliceOfKind(val r.Value, exp r.Kind) r.Value
- func ValidateStruct(val r.Value) r.Value
- func ValidateTypeFunc(typ r.Type) r.Type
- func ValidateTypeKind(typ r.Type, exp r.Kind) r.Type
- func ValidateTypeMap(typ r.Type) r.Type
- func ValidateTypePtr(typ r.Type) r.Type
- func ValidateTypeSlice(typ r.Type) r.Type
- func ValidateTypeStruct(typ r.Type) r.Type
- func ValidateValueKind(val r.Value, exp r.Kind) r.Value
- func ValueDeref(val r.Value) r.Value
- func ValueLen(val r.Value) int
- func ValueType(val r.Value) r.Type
- func Walk(val r.Value, fil Filter, vis Visitor)
- func WalkFunc(val r.Value, fil Filter, vis VisitorFunc)
- func Zero(ptr interface{})
- type All
- type And
- type Appender
- type Both
- type Cache
- type Desc
- type Err
- type Filter
- type IfaceFilter
- type InvertSelf
- type Nop
- type Or
- type Self
- type TagFilter
- type TypeFilter
- type Visitor
- type VisitorFunc
- type Walker
Constants ¶
const ( // Don't visit self or descendants. Being zero, this is the default. VisNone = 0b_0000_0000 // Visit self. VisSelf = 0b_0000_0001 // Visit descendants. VisDesc = 0b_0000_0010 // Visit both self and descendants. VisBoth = VisSelf | VisDesc // Same effect as `rf.VisBoth`. Provided for arithmetic. VisAll = 0b_1111_1111 )
Flags constituting the return value of `rf.Filter`. Unknown bits will be ignored.
Variables ¶
This section is empty.
Functions ¶
func CopyPath ¶
Shortcut for copying struct field paths, suitable for `reflect.StructField.Index`. Such copying is required when walking a struct type to build a collection of fields for later use (such representations should also be cached via `rf.Cache`).
func DerefKind ¶
Shortcut for `rf.TypeKind(rf.DerefType(val))`. Returns the kind of the provided value, automatically dereferencing any outer pointer types until it finds a non-pointer type. If the input is nil, returns `reflect.Invalid`.
func DerefSlice ¶
Shortcut for `rf.DerefValueWithKind(val, reflect.Slice)`.
func DerefStruct ¶
Shortcut for `rf.DerefValueWithKind(val, reflect.Struct)`.
func DerefType ¶
Same as `reflect.TypeOf`, but dereferences the type, allowing to pass a nil pointer, which doesn't allocate. The following expressions both produce the type of `time.Time`, but the second one is cheaper:
rf.DerefType(time.Time{}) // Allocates.
rf.DerefType((*time.Time)(nil)) // Doesn't allocate.
func DerefValue ¶
Shortcut for `rf.ValueDeref(reflect.ValueOf(val))`. Returns the `reflect.Value` of the input, automatically dereferencing any outer pointers. If any outer pointers are nil, returns `reflect.Value{}`.
func DerefValueWithKind ¶
Ensures that the given value either directly or indirectly (through any number of arbitrarily-nested pointer types) contains a type of the provided kind, and returns its dereferenced value. If any intermediary pointer is nil, the returned value is invalid.
func ElemType ¶
Shortcut for `rf.TypeElem(reflect.TypeOf(val))`. Returns the element type of the given value, automatically dereferencing pointer AND slice types, until it finds the first non-pointer, non-slice type. If the input is nil, returns nil.
func Fields ¶ added in v0.2.2
func Fields(typ interface{}) []r.StructField
Shortcut for `rf.TypeFields(rf.DerefType(typ))`.
func FuncName ¶
func FuncName(val interface{}) string
Returns the name of a given function, if possible. Returns "" for nil.
func IsColl ¶
func IsColl(val interface{}) bool
True if the kind of the provided value is a collection. See `rf.IsKindColl` for further details. Note that this follows `reflect.Value.Len` rather than the built-in `len` in that pointers to arrays are not considered to be collections.
func IsEmbed ¶
func IsEmbed(val r.StructField) bool
True if the given field represents an embedded non-pointer struct type. False if it's embedded by pointer.
func IsEmptyColl ¶
func IsEmptyColl(val interface{}) bool
True if the input belongs to one of the kinds "reflect" considers collections (see `rf.IsKindColl`), and has the length of zero. If the input is a non-nil interface that describes a nil collection, such as `([]string)(nil)`, this returns true. If the input is a nil interface, this returns false. Doesn't automatically dereference the input.
func IsKindColl ¶
True for the kinds "reflect" considers collections: array, chan, map, slice, or string. These are the kinds for which it's safe to call `reflect.Value.Len` without panicking.
func IsKindNilable ¶
True for kinds on which it's safe to call `reflect.Value.IsNil`.
func IsNil ¶
func IsNil(val interface{}) bool
True if the input is a nil interface or a non-nil interface containing a nil value. See `rf.IsValueNil`.
func IsPublic ¶
True if the input string is empty. Allows to clarify reflection code that checks the public/private status of struct fields and type methods. Examples (oversimplified):
rf.IsPublic(reflect.StructField{}.PkgPath)
rf.IsPublic(reflect.Method{}.PkgPath)
func IsValueEmptyColl ¶
Variant of `rf.IsEmpty` that takes a `reflect.Value` as input. See `rf.IsEmpty` for the documentation.
func IsValueNil ¶
True if the input is invalid or contains a nilable value that is nil. Automatically dereferences pointers, returning true for a non-nil pointer to a nil value.
func IsValueZero ¶
True if the input is nil (as defined by `rf.IsValueNil`) or a zero value of its type. Automatically dereferences pointers.
func IsZero ¶
func IsZero(val interface{}) bool
Shortcut for `rf.IsValueZero(reflect.ValueOf(val))`. True if the input is nil or a zero value of its type. Automatically dereferences the input; an arbitrarily-nested non-nil pointer to a zero value is considered zero.
func Iter ¶
func Iter(count int) []struct{}
Zero-cost integer iterator. Usage:
for range rf.Iter(N) { ... }
for i := range rf.Iter(N) { ... }
Because `struct{}` is zero-sized, `[]struct{}` is backed by "zerobase" (see "runtime/malloc.go") and does not allocate. This should perform about as well as a "normal" counted loop.
This is not reflection related, but exported because it's used internally a lot.
func Kind ¶
Same as `reflect.TypeOf(val).Kind()`, but returns `reflect.Invalid` for a nil input, instead of panicking. Doesn't automatically dereference the input.
func Len ¶ added in v0.3.0
func Len(val interface{}) int
Shortcut for `rf.ValueLen(rf.DerefValue(val))`. Returns the length of the given value, if possible. If not, returns 0. Automatically dereferences the input.
func NormNil ¶
func NormNil(val interface{}) interface{}
Short for "normalize nil". If the input is a non-nil interface whose underlying value is nil, this normalizes it, returning a nil interface. Otherwise this returns the input as-is.
func SliceType ¶
Shortcut for `reflect.SliceOf(DerefType(val))`. The following expressions are all equivalent:
reflect.SliceOf(reflect.TypeOf(``)) reflect.SliceOf(reflect.TypeOf((*string)(nil)).Elem()) rf.SliceType(``) rf.SliceType((*string)(nil))
func TagIdent ¶
Takes a struct field tag and returns its identifier part, following the "encoding/json" conventions. Ident "-" is converted to "". Usage:
ident := rf.TagIdent(someField.Tag.Get(`json`)) ident := rf.TagIdent(someField.Tag.Get(`db`))
Rules:
json:"ident" -> "ident" json:"ident,<extra>" -> "ident" json:"-" -> "" json:"-,<extra>" -> ""
func Trawl ¶
func Trawl(src, out interface{})
Shortcut for `rf.TrawlWith` without an additional filter. Takes an arbitrary source value and a pointer to an output slice. Walks the source value, appending all non-zero values of the matching type to the given slice.
func TrawlWith ¶
func TrawlWith(src, out interface{}, fil Filter)
Shortcut for using `rf.Appender` and `rf.Walk` to trawl the provided "source" value to collect all non-zero values of a specific type into an "output" slice. The source value may be of arbitrary type. The output must be a non-nil pointer to a slice. The additional filter is optional.
func TypeDeref ¶
Returns the element type of the provided type, automatically dereferencing pointer types. If the input is nil, returns nil.
func TypeElem ¶
Returns the element type of the provided type, automatically dereferencing pointer AND slice types, until it finds the first non-pointer, non-slice type. If the input is nil, returns nil.
func TypeFields ¶ added in v0.2.2
func TypeFields(typ r.Type) []r.StructField
Takes a struct type and returns its fields, caching and reusing the resulting slice for all future calls for each type. The resulting slice or its elements must not be mutated.
func TypeKind ¶
Same as `reflect.Type.Kind(val)`, but returns `reflect.Invalid` for a nil input, instead of panicking. Doesn't automatically dereference the input.
func ValidPtrToKind ¶
Shortcut for `rf.ValidatePtrToKind(reflect.ValueOf(val))`. Converts the input to `reflect.Value`, ensures that it's a non-nil pointer where the inner type has the required kind, and returns the resulting `reflect.Value`.
func ValidSlice ¶
Shortcut for `rf.ValidateSlice(reflect.ValueOf(val))`.
func ValidSliceOf ¶
Shortcut for `rf.ValidateSliceOf(reflect.ValueOf(val))`. Converts the input to `reflect.Value`, ensures that it's a slice with the required element type, and returns the resulting `reflect.Value`.
func ValidSliceOfKind ¶
Shortcut for `rf.ValidateSliceOfKind(reflect.ValueOf(val))`. Converts the input to `reflect.Value`, ensures that it's a slice where the element type has the required kind, and returns the resulting `reflect.Value`.
func ValidStruct ¶
Shortcut for `rf.ValidateStruct(reflect.ValueOf(val))`.
func ValidTypeFunc ¶
Shortcut for `rf.ValidateTypeFunc(reflect.TypeOf(val))`.
func ValidTypeMap ¶
Shortcut for `rf.ValidateTypeMap(reflect.TypeOf(val))`.
func ValidTypePtr ¶
Shortcut for `rf.ValidateTypePtr(reflect.TypeOf(val))`.
func ValidTypeSlice ¶
Shortcut for `rf.ValidateTypeSlice(reflect.TypeOf(val))`.
func ValidTypeStruct ¶
Shortcut for `rf.ValidateTypeStruct(reflect.TypeOf(val))`.
func ValidateFunc ¶
Shortcut for `rf.ValidateValueKind(val, reflect.Func)`.
func ValidateFuncIn ¶
Takes a func type and ensures that its input parameters exactly match the count and types provided to this function, or panics with a descriptive error. Among the provided parameter types, nil serves as a wildcard that matches any type.
func ValidateFuncNumIn ¶
Takes a func type and ensures that it has the required count of input parameters, or panics with a descriptive error.
func ValidateFuncNumOut ¶
Takes a func type and ensures that it has the required count of output parameters, or panics with a descriptive error.
func ValidateFuncOut ¶
Takes a func type and ensures that its return parameters exactly match the count and types provided to this function, or panics with a descriptive error. Among the provided parameter types, nil serves as a wildcard that matches any type.
func ValidateMap ¶
Shortcut for `rf.ValidateValueKind(val, reflect.Map)`.
func ValidatePtr ¶
Similar to `rf.ValidateValueKind(val, reflect.Ptr)`, but also ensures that the pointer is non-nil.
func ValidatePtrToKind ¶
Ensures that the value is a non-nil pointer where the underlying type has the required kind, or panics with a descriptive error. Returns the same value, allowing shorter code. Supports pointers of any depth: `*T`, `**T`, etc. Known limitation: only the outermost pointer is required to be non-nil. Inner pointers may be nil.
func ValidateSlice ¶
Shortcut for `rf.ValidateValueKind(val, reflect.Slice)`.
func ValidateSliceOf ¶
Ensures that the value is a slice where the element type has the required type, or panics with a descriptive error. Returns the same value, allowing shorter code. Doesn't automatically dereference the input.
func ValidateSliceOfKind ¶
Ensures that the value is a slice where the element type has the required kind, or panics with a descriptive error. Returns the same value, allowing shorter code. Doesn't automatically dereference the input.
func ValidateStruct ¶
Shortcut for `rf.ValidateValueKind(val, reflect.Struct)`.
func ValidateTypeFunc ¶
Shortcut for `rf.ValidateTypeKind(typ, reflect.Func)`.
func ValidateTypeKind ¶
Ensures that the type has the required kind or panics with a descriptive error. Returns the same type, allowing shorter code.
func ValidateTypeMap ¶
Shortcut for `rf.ValidateTypeKind(typ, reflect.Map)`.
func ValidateTypePtr ¶
Shortcut for `rf.ValidateTypeKind(typ, reflect.Ptr)`.
func ValidateTypeSlice ¶
Shortcut for `rf.ValidateTypeKind(typ, reflect.Slice)`.
func ValidateTypeStruct ¶
Shortcut for `rf.ValidateTypeKind(typ, reflect.Struct)`.
func ValidateValueKind ¶
Ensures that the value has the required kind or panics with a descriptive error. Returns the same value, allowing shorter code.
func ValueDeref ¶
Dereferences the provided value until it's no longer a pointer. If the input is a nil pointer or a pointer to a nil pointer (recursively), this returns `reflect.Value{}`.
func ValueLen ¶
If the provided value is a collection via `rf.IsColl`, returns the result of calling `reflect.Value.Len`. Otherwise returns 0. Doesn't automatically dereference the input.
func ValueType ¶
Same as `reflect.Value.Type` but "safe" to call on invalid value, in which case this will return nil. Should be used only when nil output type is acceptable.
func Walk ¶
Takes an arbitrary value and performs deep traversal, invoking the visitor for each node allowed by the filter. Internally, uses `rf.GetWalker` to get or create a walker specialized for this combination of type and filter. For each type+filter combination, `rf.GetWalker` generates a specialized walker, caching it for future calls. This approach allows MUCH more efficient walking.
Types ¶
type All ¶ added in v0.3.0
type All struct{}
Implementation of `rf.Filter` that always returns `rf.VisAll`.
type And ¶
type And [8]Filter
Implementation of `rf.Filter` that combines other filters, AND-ing their outputs via `&`. Nil elements are ignored. If all elements are nil, the output is automatically `VisNone`.
type Appender ¶
Implementation of `rf.Visitor` for collecting non-zero values of a single type into a slice. The inner value must be `reflect.Value` holding a slice. The value must be settable. Use `rf.AppenderFor` to instantiate this correctly.
func AppenderFor ¶
func AppenderFor(typ interface{}) Appender
Shortcut for making `rf.Appender`. The input must be a carrier of the element type, not the slice type.
func (Appender) Filter ¶
Returns a filter that allows to visit only values suitable to be elements of the slice held by the appender.
type Both ¶ added in v0.3.0
type Both struct{}
Implementation of `rf.Filter` that always returns `rf.VisBoth`.
type Cache ¶
Tiny shortcut for caching arbitrary structures keyed by `reflect.Type`. Any reflection-based code that involves walking arbitrary structs should use `rf.Cache` to "compile" a specialized structure optimized for that particular traversal, and reuse it for subsequent invocations.
type Desc ¶ added in v0.3.0
type Desc struct{}
Implementation of `rf.Filter` that always returns `rf.VisDesc`.
type Filter ¶
type Filter interface {
Visit(r.Type, r.StructField) byte
}
Tool for implementing efficient reflect-based deep walking. Determines if a particular node should be visited during a walk, and how. This package provides several filter implementations, such as filtering by type, by struct tag, or combining other filters.
The return value of `rf.Filter.Visit` is a combination of two optional flags: `rf.VisSelf` and `rf.VisDesc`. Flags are combined with bitwise OR. The following combinations are known:
return VisNone // Zero value / default. return VisSelf return VisDesc return VisSelf | VisDesc return VisBoth // Shortcut for the above.
If the flag `rf.VisDesc` is set, we attempt to generate an inner walker that visits the descendants of the current node, such as the elements of a slice, the fields of a struct, the value behind a pointer, or the value referenced by an interface. Otherwise, we don't attempt to generate an inner walker.
If the flag `rf.VisSelf` is set, we generate a walker that invokes `Visitor.Visit` on the current node. Otherwise the resulting walker will not visit the current node, and may possibly be nil.
For technical reasons, all implementations of this interface must be values rather than references. For example, filters provided by this package must be used as values rather than pointers. The following is the CORRECT way to construct filters:
var filter rf.Filter = rf.And{
TypeFilterFor((*string)(nil)),
rf.TagFilter{`json`, `fieldName`},
}
The following is the INCORRECT way to construct filters. Due to internal validation, this will cause panics at runtime:
var filter rf.Filter = &rf.And{
&rf.TypeFilter{rf.DerefType((*string)(nil))},
&rf.TagFilter{`json`, `fieldName`},
}
See also:
rf.Walker rf.Visitor rf.GetWalker rf.Walk
func MaybeAnd ¶ added in v0.2.1
Micro-optimization for `rf.And`. If the input has NO non-nil filters, returns nil. If the input has ONE non-nil filter, returns that filter, avoiding an allocation of `rf.And{}`. Otherwise combines the filters via `rf.And`.
func MaybeOr ¶ added in v0.2.1
Micro-optimization for `rf.Or`. If the input has NO non-nil filters, returns nil. If the input has ONE non-nil filter, returns that filter, avoiding an allocation of `rf.Or{}`. Otherwise combines the filters via `rf.Or`.
func TypeFilterFor ¶ added in v0.2.1
func TypeFilterFor(typ interface{}) Filter
Shortcut, same as `rf.GetTypeFilter(rf.DerefType(typ))`.
type IfaceFilter ¶ added in v0.3.0
Implementation of `rf.Filter` that allows to visit values whose types implement the given interface BY POINTER. The inner type must be non-nil and represent an interface, otherwise this will panic. Unlike `rf.TypeFilter`, this visits either self or descendants, not both. The visitor must explicitly take value address:
func visit(val r.Value, _ r.StructField) {
val.Addr().Interface().(SomeInterface).SomeMethod()
}
func (IfaceFilter) Visit ¶ added in v0.3.0
func (self IfaceFilter) Visit(typ r.Type, _ r.StructField) byte
Implement `rf.Filter`.
type InvertSelf ¶ added in v0.3.0
type InvertSelf [1]Filter
Implementation of `rf.Filter` that inverts the "self" bit of the inner filter, without changing the other flags. If the inner filter is nil, this always returns `rf.VisNone`.
func (InvertSelf) Visit ¶ added in v0.3.0
func (self InvertSelf) Visit(typ r.Type, field r.StructField) byte
Implement `rf.Filter`.
type Nop ¶
type Nop struct{}
No-op implementation of both `rf.Visitor` that does nothing upon visit.
type Or ¶
type Or [8]Filter
Implementation of `rf.Filter` that combines other filters, OR-ing their outputs via `|`. Nil elements are ignored. If all elements are nil, the output is automatically `VisNone`.
type Self ¶ added in v0.3.0
type Self struct{}
Implementation of `rf.Filter` that always returns `rf.VisSelf`.
type TagFilter ¶
type TagFilter [2]string
Implementation of `rf.Filter` that allows to visit values whose struct tag has a specific tag with a specific value, such as tag "json" with value "-". It also allows to visit descendants.
type TypeFilter ¶
Implementation of `rf.Filter` that allows to visit values of this specific type. The type may be either concrete or an interface. In all cases, it also allows to visit descendants.
func (TypeFilter) Visit ¶ added in v0.3.0
func (self TypeFilter) Visit(typ r.Type, _ r.StructField) byte
Implement `rf.Filter`.
type Visitor ¶
type Visitor interface {
Visit(r.Value, r.StructField)
}
Used by `rf.Walker` and `rf.Walk` to visit certain nodes of the given value. A visitor can be an arbitrary value or a function; see `rf.VisitorFunc`.
type VisitorFunc ¶
type VisitorFunc func(r.Value, r.StructField)
Function type that implements `rf.Visitor`. Used by `rf.WalkFunc`. Converting a func to an interface value is alloc-free.
func (VisitorFunc) Visit ¶
func (self VisitorFunc) Visit(val r.Value, field r.StructField)
Implement `rf.Visitor` by calling itself.
type Walker ¶
Tool for implementing efficient reflect-based deep walking. The function `rf.GetWalker` generates a walker for a SPECIFIC combination of parent type and `rf.Filter`. The resulting walker is specialized for that combination, and walks its input precisely and efficiently.
For simplicity and efficiency reasons, walkers generated by this package don't additionally assert that the provided `reflect.Value` has the same type for which the walker is generated. When using `rf.Walk` or `rf.WalkFunc`, this is handled for you. Otherwise, it's your responsibility to pass a value of the same type. For simplicity, walkers also assume that the visitor is non-nil.
This package currently does NOT support walking into maps, for two reasons: unclear semantics and inefficiency. It's unclear if we should walk keys, values, or key-value pairs, and how that affects the rest of the walking API. Currently in Go 1.17, reflect-based map walking has horrible inefficiencies which can't be amortized by 3rd party code. It would be a massive performance footgun.
This package does support walking into interface values included into other structures, but at an efficiency loss. In general, our walking mechanism relies on statically determining what we should and shouldn't visit, which is possible only with static types. Using interfaces as dynamically-typed containers of unknown values defeats this design by forcing us to always visit each of them, and may produce significant slowdowns. However, while visiting each interface value is an unfortunate inefficiency, walking the value REFERENCED by an interface is as precise and efficient as with static types.
func GetWalker ¶
Returns an `rf.Walker` for the given type with the given filter. Uses caching to avoid generating a walker more than once. Future calls with the same inputs will return the same walker instance. Returns nil if for this combination of type and filter, nothing will be visited. A nil filter is equivalent to a filter that always returns false, resulting in a nil walker.