reflect.ValueOf(i interface{})

Reflect ValueOf can convert a variable to reflect.Value

  • Reflect. Value represents the actual Value of the variable, or returns 0 if the interface is empty.

  • The reflect.value type provides a Kind() method that gets the actual type of the variable.

  • The reflect.value Type provides the Type() method to get the actual Type of the variable, which can be analogous to TypeOf()

var i int
value := reflect.ValueOf(i)

fmt.Println(value)        / / output: 0
fmt.Println(value.Type()) / / output: int
fmt.Println(value.Kind()) / / output: int


type S struct {
  A string
}

var s = S{"SSS"}
value2 := reflect.ValueOf(s) // Get the structure's Value object with ValueOf()

fmt.Println(value2)        / / output: {} SSS
fmt.Println(value2.Type()) / / output: the main S
fmt.Println(value2.Kind()) / / output: struct
Copy the code

The variable I outputs an int using both Kind() and Type(), while the Type() method of structure S outputs s and the Kind() method outputs a struct

To summarize, if you want to get the Type of a structure, use the Type() method. If it’s just a phase, you use Kind()

type MyInt8 int8
var num MyInt8 = 1

val := reflect.ValueOf(num)
fmt.Println(val.Type()) // main.MyInt8
fmt.Println(val.Kind()) // int8
Copy the code

In the above code, the Kind method still returns reflect.int, even though the static type of v is MyInt, not int. In other words, the Kind method does not distinguish between MyInt and int the way the Type method does.

setter and getter

The Value type also has methods like Int and Float to extract the underlying data

var x float64 = 3.4
v := reflect.ValueOf(x)

fmt.Println("value:", v.Float()) / / output: 3.4

var x uint8 = 'x'
v := reflect.ValueOf(x)
fmt.Println("type:", v.Type())       // uint8.

fmt.Println("kind is uint8: ", v.Kind() == reflect.Uint8) // true.
x = uint8(v.Uint())    // v.Uint returns a uint64.
Copy the code

The Value Int method returns an int64 Value, and the SetInt method receives an int64 parameter. For practical use, you may need to convert to the actual type

If the setter’s function is not of the corresponding type and causes the program to panic, the following program will panic

var num int8 = 1

val := reflect.ValueOf(num)
fmt.Println(val.Uint())

// panic: reflect: call of reflect.Value.Uint on int8 Value
Copy the code

But there is no panic for the following uses

type MyInt8 int8
var num MyInt8 = 1

val := reflect.ValueOf(num)
fmt.Println(val.Int())
Copy the code
var num float64 = 1.2345

// Reflect. ValueOf gets reflect.Value in num. Note that the argument must be a pointer to change its Value
pointer := reflect.ValueOf(&num)
newValue := pointer.Elem()

fmt.Println(pointer.Type())    // Output: *float64
fmt.Println(newValue.Type())   // Output: float64
fmt.Println(newValue.CanSet()) // Output: true

// reassign
newValue.SetFloat(77)
fmt.Println("new value of pointer:", num) // Output: 77

////////////////////
// What happens if reflect.valueof's argument is not a pointer?
pointer = reflect.ValueOf(num)
//newValue = pointer.elem () // If it is not a pointer, panic, "panic: reflect: call of reflect.value. Elem on float64 Value"
Copy the code

The Value of the actual variable X can only be modified through reflec.Value if X is a pointer, that is, to modify objects of reflection type, ensure that their values are “addressable” (see Resources -1 for reasons).

Only exposed fields in structs are “writable”

Reflect.value.elem () retrieves the reflection object corresponding to the original Value. Only the original object can be modified, but the current reflection object cannot be modified

For indeterminate Pointers you can use reflect.indirect (value)

from reflection object to interface value

The relect.Value variable can be used to obtain the real content of the Interface variable through its own Interface() method, and then can be converted to the original real type through type judgment

y := v.Interface().(float64) // y will have type float64.
fmt.Println(y)
Copy the code

At moments of indeterminate type

var num int8 = 1

val := reflect.ValueOf(&num).Elem()

var s string
switch val.Interface().(type) {
  case int.int8.int32.int64:
  s = strconv.FormatInt(val.Int(), 10)
}

fmt.Println(s)
Copy the code

That’s fine

var s string
switch val.Kind() {
  case reflect.Int8:
  s = strconv.FormatInt(val.Int(), 10)}Copy the code

struct

For scalar types, we can use functions like v.int () to get the actual value directly. For struct types, we can use type assertions (ValueOf().interface ().(struct)) if the type is known.

field

For unknown structs it is possible to traverse each field of the structure in the following manner

type S struct {
  A string
  B int
}

var s = S{"SSS".1}
val := reflect.ValueOf(s)

for i := 0; i < val.NumField(); i++{ fmt.Println(val.Field(i)) }Copy the code

Among them

Val.numfield () gets the number of structure fields

Val. Field(I int) Value retrieves the ith Field

Of course you can use the other two functions

type S struct {
  A string
  B int
  C struct {
    D []int}}var s = S{"SSS".1.struct{ D []int} {[]int{1.2.3}}}
val := reflect.ValueOf(s)

fmt.Println(val.FieldByIndex([]int{2.0})) // output: [1, 2, 3]
fmt.Println(val.FieldByName("B"))          // Output: 1
Copy the code

method

Struct types also refer to struct owning methods (functions), which are used in the same way as retrieving fields

for i := 0; i < val.NumMethod(); i++ {
  fmt.Println(val.Method(i))
}
Copy the code

The call function takes a slice of the function’s arguments and returns a slice of the return value

type S struct {
	A string
	B int `json:"tag"`
}

func (t S) Mth(p string) (string.int) {
	return t.A + p, t.B
}

s := S{"SSS".1}

val := reflect.ValueOf(s)
m2 := val.MethodByName("Mth")

params := []reflect.Value{reflect.ValueOf("AAA")}
fmt.Println(m2.Call(params)[0].String()) // Output: SSSAAA
Copy the code

All of the above functions panic for non-structs

For a call, the number of slices passed in needs to match the number of functions, otherwise panic will also occur

reflect.TypeOf(i interface{})

TypeOf converts variables to reflect.Type,

  • Reflect. Type represents the actual Type of the variable, or returns nil if the interface is empty. This can be analogous to ValueOf().type ()

  • Relect.Type provides the Kind() method to get the Type of variable.

var i int
value := reflect.TypeOf(i)

fmt.Println(value2)       // Output: int
fmt.Println(value.Type()) // output: value.Type undefined (TypeOf does not have Type function)
fmt.Println(value.Kind()) // Output: int


type S struct {
  a string
}

var s S
value2 := reflect.TypeOf(s) // Use TypeOf() to get the structure's Type object

fmt.Println(value2)        / / output main. S
fmt.Println(value2.Type()) // output :value2.Type undefined (TypeOf does not have Type function)
fmt.Println(value2.Kind()) / / output: struct
Copy the code

struct

For struct TypeOf, properties and functions can be traversed in the following manner.


type S struct {
	A string
	B int `json: "b"`
}

func (t S) Mth(a){
	return
}

var s = S{"SSS".1}
typ := reflect.TypeOf(s)
for i := 0; i < typ.NumField(); i++ {
  f := typ.Field(i)
  fmt.Println(f.Name, f.Type)
}

for i := 0; i < typ.NumMethod(); i++ {
  m := typ.Method(i)
  fmt.Println(m.Name, m.Func)
}
Copy the code

Pay attention to andValuethefieldRelevant functions are distinguished:

The reflect.Type field-related function returns the reflect.StructField Type, which gets the field name and field Type

Field(i int) StructField

FieldByIndex(index []int) StructField

FieldByName(name string) (StructField, bool)
Copy the code

The reflect.Value field-related function returns type reflect.Value

func (v Value) Field(i int) Value

func (v Value) FieldByIndex(index []int) Value 

func (v Value) FieldByName(name string) Value
Copy the code

One thing to note about reflect.structField is that you can get tag values

type S struct {
	A string
	B int `json:"tag"`
}

s := S{"SSS".1}

typ := reflect.TypeOf(s)
f, _ := typ.FieldByName("B")

fmt.Println(f.Tag.Get("json")) // Output: tag
Copy the code

The resources

  • Blog.golang.org/laws-of-ref…
  • www.jb51.net/article/900…