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 >>> }