Involved Source Files Package reflections provides high level abstractions over the Go standard [reflect] library.
In practice, the `reflect` library's API proves somewhat low-level and un-intuitive.
Using it can turn out pretty complex, daunting, and scary, when doing simple
things like accessing a structure field value, a field tag, etc.
The `reflections` package aims to make developers' life easier when it comes to introspect
struct values at runtime. Its API takes inspiration in the python language's `getattr,` `setattr,` and `hasattr` set
of methods and provides simplified access to structure fields and tags.
Code Examples
package main
import (
"fmt"
"github.com/oleiade/reflections"
)
type MyStruct struct {
MyEmbeddedStruct
FirstField string `matched:"first tag"`
SecondField int `matched:"second tag"`
ThirdField string `unmatched:"third tag"`
}
type MyEmbeddedStruct struct {
EmbeddedField string
}
func main() {
s := MyStruct{
FirstField: "first value",
SecondField: 2,
ThirdField: "third value",
}
var fields []string
// Fields will list every structure exportable fields.
// Here, it's content would be equal to:
// []string{"FirstField", "SecondField", "ThirdField"}
fields, _ = reflections.Fields(s)
fmt.Println(fields)
}
package main
import (
"fmt"
"log"
"github.com/oleiade/reflections"
)
type MyStruct struct {
MyEmbeddedStruct
FirstField string `matched:"first tag"`
SecondField int `matched:"second tag"`
ThirdField string `unmatched:"third tag"`
}
type MyEmbeddedStruct struct {
EmbeddedField string
}
func main() {
s := MyStruct{
FirstField: "first value",
SecondField: 2,
ThirdField: "third value",
}
fieldsToExtract := []string{"FirstField", "ThirdField"}
for _, fieldName := range fieldsToExtract {
value, err := reflections.GetField(s, fieldName)
if err != nil {
log.Fatal(err)
}
fmt.Println(value)
}
}
package main
import (
"fmt"
"log"
"reflect"
"github.com/oleiade/reflections"
)
type MyStruct struct {
MyEmbeddedStruct
FirstField string `matched:"first tag"`
SecondField int `matched:"second tag"`
ThirdField string `unmatched:"third tag"`
}
type MyEmbeddedStruct struct {
EmbeddedField string
}
func main() {
s := MyStruct{
FirstField: "first value",
SecondField: 2,
ThirdField: "third value",
}
var firstFieldKind reflect.Kind
var secondFieldKind reflect.Kind
var err error
// GetFieldKind will return reflect.String
firstFieldKind, err = reflections.GetFieldKind(s, "FirstField")
if err != nil {
log.Fatal(err)
}
fmt.Println(firstFieldKind)
// GetFieldKind will return reflect.Int
secondFieldKind, err = reflections.GetFieldKind(s, "SecondField")
if err != nil {
log.Fatal(err)
}
fmt.Println(secondFieldKind)
}
package main
import (
"encoding/json"
"fmt"
"log"
"github.com/oleiade/reflections"
)
func main() {
type Order struct {
Step string `json:"order_step"`
ID string `json:"id"`
Category string `json:"category"`
}
type Condition struct {
Field string `json:"field"`
Value string `json:"value"`
Next string `json:"next"`
}
// JSON data from external source
orderJSON := `{
"order_step": "cooking",
"id": "45457-fv54f54",
"category": "Pizzas"
}`
conditionJSON := `{
"field": "order_step",
"value": "cooking",
"next": "serve"
}`
// Storing JSON in corresponding Variables
var order Order
err := json.Unmarshal([]byte(orderJSON), &order)
if err != nil {
log.Fatal(err)
}
var condition Condition
err = json.Unmarshal([]byte(conditionJSON), &condition)
if err != nil {
log.Fatal(err)
}
fieldName, _ := reflections.GetFieldNameByTagValue(order, "json", condition.Field)
fmt.Println(fieldName)
fieldValue, _ := reflections.GetField(order, fieldName)
fmt.Println(fieldValue)
}
package main
import (
"fmt"
"log"
"github.com/oleiade/reflections"
)
type MyStruct struct {
MyEmbeddedStruct
FirstField string `matched:"first tag"`
SecondField int `matched:"second tag"`
ThirdField string `unmatched:"third tag"`
}
type MyEmbeddedStruct struct {
EmbeddedField string
}
func main() {
s := MyStruct{}
tag, err := reflections.GetFieldTag(s, "FirstField", "matched")
if err != nil {
log.Fatal(err)
}
fmt.Println(tag)
tag, err = reflections.GetFieldTag(s, "ThirdField", "unmatched")
if err != nil {
log.Fatal(err)
}
fmt.Println(tag)
}
package main
import (
"fmt"
"log"
"github.com/oleiade/reflections"
)
type MyStruct struct {
MyEmbeddedStruct
FirstField string `matched:"first tag"`
SecondField int `matched:"second tag"`
ThirdField string `unmatched:"third tag"`
}
type MyEmbeddedStruct struct {
EmbeddedField string
}
func main() {
s := MyStruct{
FirstField: "first value",
SecondField: 2,
ThirdField: "third value",
}
var firstFieldType string
var secondFieldType string
var err error
// GetFieldType will return reflect.String
firstFieldType, err = reflections.GetFieldType(s, "FirstField")
if err != nil {
log.Fatal(err)
}
fmt.Println(firstFieldType)
// GetFieldType will return reflect.Int
secondFieldType, err = reflections.GetFieldType(s, "SecondField")
if err != nil {
log.Fatal(err)
}
fmt.Println(secondFieldType)
}
package main
import (
"fmt"
"github.com/oleiade/reflections"
)
type MyStruct struct {
MyEmbeddedStruct
FirstField string `matched:"first tag"`
SecondField int `matched:"second tag"`
ThirdField string `unmatched:"third tag"`
}
type MyEmbeddedStruct struct {
EmbeddedField string
}
func main() {
s := MyStruct{
FirstField: "first value",
SecondField: 2,
ThirdField: "third value",
}
// has == true
has, _ := reflections.HasField(s, "FirstField")
fmt.Println(has)
// has == false
has, _ = reflections.HasField(s, "FourthField")
fmt.Println(has)
}
package main
import (
"fmt"
"github.com/oleiade/reflections"
)
type MyStruct struct {
MyEmbeddedStruct
FirstField string `matched:"first tag"`
SecondField int `matched:"second tag"`
ThirdField string `unmatched:"third tag"`
}
type MyEmbeddedStruct struct {
EmbeddedField string
}
func main() {
s := MyStruct{
FirstField: "first value",
SecondField: 2,
ThirdField: "third value",
}
var structItems map[string]interface{}
// Items will return a field name to
// field value map
structItems, _ = reflections.Items(s)
fmt.Println(structItems)
}
package main
import (
"fmt"
"github.com/oleiade/reflections"
)
type MyStruct struct {
MyEmbeddedStruct
FirstField string `matched:"first tag"`
SecondField int `matched:"second tag"`
ThirdField string `unmatched:"third tag"`
}
type MyEmbeddedStruct struct {
EmbeddedField string
}
func main() {
s := MyStruct{
FirstField: "first value",
SecondField: 2,
ThirdField: "third value",
MyEmbeddedStruct: MyEmbeddedStruct{
EmbeddedField: "embedded value",
},
}
var structItems map[string]interface{}
// ItemsDeep will return a field name to
// field value map, including fields from
// anonymous embedded structs
structItems, _ = reflections.ItemsDeep(s)
fmt.Println(structItems)
}
package main
import (
"log"
"github.com/oleiade/reflections"
)
type MyStruct struct {
MyEmbeddedStruct
FirstField string `matched:"first tag"`
SecondField int `matched:"second tag"`
ThirdField string `unmatched:"third tag"`
}
type MyEmbeddedStruct struct {
EmbeddedField string
}
func main() {
s := MyStruct{
FirstField: "first value",
SecondField: 2,
ThirdField: "third value",
}
// In order to be able to set the structure's values,
// a pointer to it has to be passed to it.
err := reflections.SetField(&s, "FirstField", "new value")
if err != nil {
log.Fatal(err)
}
// Note that if you try to set a field's value using the wrong type,
// an error will be returned
_ = reflections.SetField(&s, "FirstField", 123) // err != nil
}
package main
import (
"fmt"
"github.com/oleiade/reflections"
)
type MyStruct struct {
MyEmbeddedStruct
FirstField string `matched:"first tag"`
SecondField int `matched:"second tag"`
ThirdField string `unmatched:"third tag"`
}
type MyEmbeddedStruct struct {
EmbeddedField string
}
func main() {
s := MyStruct{
FirstField: "first value",
SecondField: 2,
ThirdField: "third value",
}
var structTags map[string]string
// Tags will return a field name to tag content
// map. Nota that only field with the tag name
// you've provided which will be matched.
// Here structTags will contain:
// {
// "FirstField": "first tag",
// "SecondField": "second tag",
// }
structTags, _ = reflections.Tags(s, "matched")
fmt.Println(structTags)
}
Package-Level Functions (total 13)
Fields returns the struct fields names list.
The `obj` parameter can either be a structure or pointer to structure.
FieldsDeep returns "flattened" fields.
Note that FieldsDeep treats fields from anonymous inner structs as normal fields.
GetField returns the value of the provided obj field.
The `obj` can either be a structure or pointer to structure.
GetFieldKind returns the kind of the provided obj field.
The `obj` can either be a structure or pointer to structure.
GetFieldNameByTagValue looks up a field with a matching `{tagKey}:"{tagValue}"` tag in the provided `obj` item.
The `obj` parameter must be a `struct`, or a `pointer` to one. If the `obj` parameter doesn't have a field tagged
with the `tagKey`, and the matching `tagValue`, this function returns an error.
GetFieldTag returns the provided obj field tag value.
The `obj` parameter can either be a structure or pointer to structure.
GetFieldType returns the kind of the provided obj field.
The `obj` can either be a structure or pointer to structure.
HasField checks if the provided `obj` struct has field named `name`.
The `obj` can either be a structure or pointer to structure.
Items returns the field:value struct pairs as a map.
The `obj` parameter can either be a structure or pointer to structure.
ItemsDeep returns "flattened" items.
Note that ItemsDeep will treat fields from anonymous inner structs as normal fields.
SetField sets the provided obj field with provided value.
The `obj` parameter must be a pointer to a struct, otherwise it soundly fails.
The provided `value` type should match with the struct field being set.
Tags lists the struct tag fields.
The `obj` can whether be a structure or pointer to structure.
TagsDeep returns "flattened" tags.
Note that TagsDeep treats fields from anonymous
inner structs as normal fields.
Package-Level Variables (total 2)
ErrUnexportedField indicates that an operation failed as a result of
applying to a non-exported struct field.
ErrUnsupportedType indicates that the provided type doesn't support the requested reflection operation.
The pages are generated with Goldsv0.8.7. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.