I have the following Go code (play.golang.org):
package main
import (
"reflect"
"fmt"
)
type User struct {
name string
email string
}
func main() {
uS := User{}
uSt := reflect.TypeOf(uS)
fmt.Println( uSt )
fmt.Println( uSt.NumField() )
// fmt.Println( uS.NumField() ) // this doesn't work, why?
}
I'm just curious here. Why we need to get the type of the struct first before calling NumField()
?
Why can't we just call it on the struct itself i.e. uS.NumField()
?
From docs:
type Value struct {
// contains filtered or unexported fields
}
func (v Value) NumField() int
I'm not quite getting what is Value
really means here. I do really appreciate concise explanation and examples.
NumField() is a function of reflected structs and can be applied on any struct once you have reflected it.
It is NOT a function of User. You did not create any functions for User, so I did to try to clarify
TypeOf returns the
reflection Type
that represents the dynamic type of i. If i is a nil interface value, TypeOf returns nil.
From above statement it is clear that TypeOf
returns reflection Type
func TypeOf(i interface{}) Type // return reflection type
Reflection type is defined in Golang as
Type is the representation of a Go type. Type values are comparable, such as with the == operator, so they can be used as map keys.
Value is the reflection interface to a Go value which you are using for Numfield method as receiver. As @Flimzy described that for any other reflection method also you need to use reflection value.
In your code:
uS := User{}
uSt := reflect.TypeOf(uS)
First value us
is assigned with User type struct. While second value uSt
is assigned as reflection Type
from the returned value of reflect.TypeOf
. Check the type of each variable:
package main
import (
"reflect"
"fmt"
)
type User struct {}
func main() {
uS := User{}
uSt := reflect.TypeOf(uS)
fmt.Printf("%T
", uS) // Print the type of uS
fmt.Printf("%T
", uSt)
}
Ouput
main.User
*reflect.rtype
For more information on how reflection works. Go through Laws of Reflection