reflect
$go get github.com/davecgh/go-spew/spew
import "github.com/davecgh/go-spew/spew"
> go: downloading github.com/davecgh/go-spew v1.1.1
import "reflect"
import "fmt"
import "strings"
// tiny formating objects
func f(s interface{}) string {
d := fmt.Sprintf("%#+v", s)
d = strings.Replace(d, "{", "{\n ", -1)
d = strings.Replace(d, "}", "\n}\n", -1)
d = strings.Replace(d, ", ", ",\n ", -1)
return d
}
Our test objects
type Test struct {
Hi string `json:"hi,omitempty"`
hi string
}
h := Test{Hi:"Ola!", hi:"privit"}
package main
import (
"fmt"
"reflect"
)
type Test struct {
Hi string `json:"hi,omitempty"`
hi string
}
func main() {
h := Test{Hi: "Ola!", hi: "privit"}
fmt.Println(reflect.ValueOf(h).FieldByName("hi").String())
}
reflect.ValueOf(h).FieldByName("hi").String()
func (t *Test) SayHello(name string, age int) (ok bool) {
return true
}
Let’s play!
var t = Test{
Hi: "!HOLA!",
hi: "Say my name %s",
}
spew.Dump(t)
> (struct { Hi string "json:\"hi,omitempty\""; 𒀸hi string }) {
> Hi: (string) (len=6) "!HOLA!",
> 𒀸hi: (string) (len=14) "Say my name %s"
> }
f(t)
result >>> struct {
result >>> Hi string "json:\"hi,omitempty\""; 𒀸hi string
result >>> }
result >>> {
result >>> Hi:"!HOLA!",
result >>> 𒀸hi:"Say my name %s"
result >>> }
spew.Dump(reflect.TypeOf(t))
> (*reflect.rtype)(0xc00058a780)(struct { Hi string "json:\"hi,omitempty\""; 𒀸hi string })
f(reflect.ValueOf(t))
result >>> struct {
result >>> Hi string "json:\"hi,omitempty\""; 𒀸hi string
result >>> }
result >>> {
result >>> Hi:"!HOLA!",
result >>> 𒀸hi:"Say my name %s"
result >>> }
f(reflect.KindOf(t))
#Type
reflect.TypeOf(int64(1)).Kind()
result >>> int64
value := int64(1)
reflect.TypeOf(value).Name()
result >>> int64
reflect.String == reflect.TypeOf(value).Kind()
result >>> false
reflect.Int64 == reflect.TypeOf(value).Kind()
result >>> true
reflect.TypeOf(reflect.String).Kind() == reflect.TypeOf(reflect.Uint8).Kind()
result >>> true
#Setting Value
var x float64 = 1.1
s := reflect.ValueOf(&x)
_, _ = fmt.Printf("%s - %t", s.Type(), s.CanSet())
// s.SetFloat(2.3)
> *float64 - false
// moving by pointer to value
v := s.Elem()
v.SetFloat(2.3)
_, _ = fmt.Printf("%s - %t", v.Type(), v.CanSet())
x
> float64 - true
result >>> 2.3
#Structs
t := Test{
Hi: "!HOLA!",
hi: "Say my name %s",
}
x := reflect.ValueOf(t)
f(t)
result >>> struct {
result >>> Hi string "json:\"hi,omitempty\""; 𒀸hi string
result >>> }
result >>> {
result >>> Hi:"!HOLA!",
result >>> 𒀸hi:"Say my name %s"
result >>> }
x.NumField()
result >>> 2
// filed by index
f(x.Field(1))
result >>> "Say my name %s"
// private field will fail
x.FieldByName("hi")
result >>> <invalid reflect.Value>
// filed by index
f(x.Field(0))
result >>> "!HOLA!"
// private field will fail
x.FieldByName("Hi")
result >>> !HOLA!
tf := reflect.TypeOf(t)
f(tf)
result >>> &reflect.rtype{
result >>> size:0x20,
result >>> ptrdata:0x18,
result >>> hash:0xcc19137c,
result >>> tflag:0x0,
result >>> align:0x8,
result >>> fieldAlign:0x8,
result >>> kind:0x19,
result >>> equal:(func(unsafe.Pointer,
result >>> unsafe.Pointer) bool)(0x8d6780),
result >>> gcdata:(*uint8)(0xc00020cc30),
result >>> str:-190,
result >>> ptrToThis:0
result >>> }
tf.NumField()
result >>> 2
tf.Field(0)
result >>> {Hi string json:"hi,omitempty" 0 [0] false}
tf.Field(1)
result >>> {𒀸hi string 16 [1] false}
tf.FieldByName("hi")
result >>> { <nil> 0 [] false} false
tf.FieldByName("Hi")
result >>> {Hi string json:"hi,omitempty" 0 [0] false} true
v1 := tf.FieldByName("Hi")
f(v1)
> // warning: expression returns 2 values, using only the first one: [reflect.StructField bool]
result >>> reflect.StructField{
result >>> Name:"Hi",
result >>> PkgPath:"",
result >>> Type:(*reflect.rtype)(0x1634720),
result >>> Tag:"json:\"hi,omitempty\"",
result >>> Offset:0x0,
result >>> Index:[]int{
result >>> 0
result >>> }
result >>> ,
result >>> Anonymous:false
result >>> }
tag := v1.Tag
tag.Get("json")
result >>> hi,omitempty
tag.Get("yaml")
result >>>
v1,e1 := tag.Lookup("json")
fmt.Sprintf("[%+v] - %t", v1, e1)
result >>> [hi,omitempty] - true
#Functions
x2 := reflect.TypeOf(t.SayHello)
x1 := reflect.TypeOf(t)
for i := 0; i < x1.NumField(); i++ {
fmt.Printf("%s\n", f(x1.Field(i)))
}
> reflect.StructField{
> Name:"Hi",
> PkgPath:"",
> Type:(*reflect.rtype)(0x1634720),
> Tag:"json:\"hi,omitempty\"",
> Offset:0x0,
> Index:[]int{
> 0
> }
> ,
> Anonymous:false
> }
>
> reflect.StructField{
> Name:"𒀸hi",
> PkgPath:"",
> Type:(*reflect.rtype)(0x1634720),
> Tag:"",
> Offset:0x10,
> Index:[]int{
> 1
> }
> ,
> Anonymous:false
> }
>
//Count inbound parameters
x2.NumIn()
result >>> 2
//Count outbound parameters
x2.NumOut()
result >>> 1
// Method
x2.String()
result >>> func(string, int) bool
x2.IsVariadic()
result >>> false
x2.PkgPath()
result >>>
var out []string
for i := 0; i < x2.NumIn(); i++ {
inV := x2.In(i)
res := fmt.Sprintf("param[%d] = kind: (%v) name: (%v)",i, inV.Kind(), inV.Name())
out = append(out, res)
}
f(out)
result >>> []string{
result >>> "param[0] = kind: (string) name: (string)",
result >>> "param[1] = kind: (int) name: (int)"
result >>> }
var out []string
for i := 0; i < x2.NumOut(); i++ {
inV := x2.In(i)
res := fmt.Sprintf("param[%d] = kind: (%v) name: (%v)",i, inV.Kind(), inV.Name())
out = append(out, res)
fmt.Printf("%s", f(inV))
}
f(out)
> &reflect.rtype{
> size:0x10,
> ptrdata:0x8,
> hash:0xe0ff5cb4,
> tflag:0x7,
> align:0x8,
> fieldAlign:0x8,
> kind:0x18,
> equal:(func(unsafe.Pointer,
> unsafe.Pointer) bool)(0x8169c0),
> gcdata:(*uint8)(0x18368b0),
> str:23238,
> ptrToThis:434144
> }
result >>> []string{
result >>> "param[0] = kind: (string) name: (string)"
result >>> }