-
Notifications
You must be signed in to change notification settings - Fork 18.4k
Description
When writing code that reflects over a struct type, it's a common requirement to know the full set of struct fields, including fields available due to embedding of anonymous members while excluding fields that are erased because they're at the same level as another field with the same name.
The logic to do this is not that complex, but it's a little subtle and easy to get wrong. I propose a new function in reflect
(or alternatively a new method on reflect.Type
) that returns the full set of effective fields that apply in a given struct type.
This method doesn't necessarily need to be hugely performant, as it's common to cache results by type.
This API seems sufficient for most use cases:
// VisibleFields returns all the visible fields in t, which must be a
// struct type. A field is defined as visible if it's accessible
// directly with a FieldByName call. The returned fields include fields
// inside anonymous struct members and unexported fields. They follow
// the same order found in the struct, with anonymous fields followed
// immediately by their promoted fields.
//
// For each element e of the returned slice, the corresponding field
// can be retrieved from a value v of type t by calling v.FieldByIndex(e.Index).
func VisibleFields(t Type) []StructField
A possible implementation is here: https://play.golang.org/p/S63fPVbo3nN
This function could of course be implemented in an external package, but for lower level codec packages, adding an external dependency can be undesirable, so copy/paste or reimplementation of similar code is common. The functionality is small enough and closely tied enough to the core reflect
logic that it seems to me that incorporating it there is reasonable.
Thanks to @mvdan and @myitcv for useful early feedback on this proposal.