This is the 8th day of my participation in the Gwen Challenge in November. See details: The Last Gwen Challenge in 2021.

Go language reflex

1 What is reflection?

Reflection is the ability of a program to examine its variables and values at run time and find their types. The three principles of reflection are as follows :: tip Three principles of reflection

  • Reflection from the boundary value to the reflection object.
  • Reflection reflects the object to the interface value.
  • To modify a reflection object, the value must be settable.

: : :

2 characteristics of reflection

::: TIP reflection features

  • The reflection function has a powerful function
  • Reflection is the ability to programmatically examine the structure, especially the type, it has
  • Is a form of metaprogramming
  • We can analyze a structure at runtime by reflection
  • Check its types and variables (types and values) and methods
  • Dynamically modify variables and call methods
  • This is especially useful for packages without source code
  • This is a powerful tool that should be avoided or used with caution unless really necessary

: : :

3 reflect bag

In the Go language, Reflect implements runtime reflection. The Reflect package helps identify the underlying concrete types and concrete values of the interface{} variable. The Reflect package has two data types as follows:

  • [reflect.typeof (): a method to get Type]
  • Value: the type of the Value [reflect.valueof (): the method used to get the Value]
  • Official reflection documentation :golang.org/pkg/reflect…

3.1 reflect. Kind

Reflect. Type and reflect.Value indicate the common Kind Type

//Kind stands for specific type.
//Invalid is not a valid type.
type Kind uint
const (
    Invalid Kind = iota  // Illegal type
    Bool                 / / the Boolean
    Int                  // Signed integer
    Int8                 // Signed 8-bit integer type
    Int16                // Signed 16-bit integer type
    Int32                // Signed 32-bit integer type
    Int64                // Signed 64-bit integer type
    Uint                 // Unsigned integer type
    Uint8                // Unsigned 8-bit integer type
    Uint16               // Unsigned 16-bit integer type
    Uint32               // Unsigned 32-bit integer type
    Uint64               // Unsigned 64-bit integer type
    Uintptr              / / pointer
    Float32              // Single-precision floating point number
    Float64              // Double precision floating point number
    Complex64            // The 64-bit complex number type
    Complex128           // 128-bit complex number type
    Array                / / array
    Chan                 / / channel
    Func                 / / function
    Interface            / / interface
    Map                  / / map
    Ptr                  / / pointer
    Slice                / / section
    String               / / string
    Struct               / / structure
    UnsafePointer        // The underlying pointer
)
Copy the code

4 Reflect.Type Description of the interface

4.1 Type Summary of interface methods

type Type interface {
    // Applies to all types of methods. Type The alignment of bytes returned during content allocation
	Align() int

	// When a type is a structured field, its byte alignment
	FieldAlign() int

    // The ith method in the method set of the method return type.
    // If I am not in the range of [0, NumMethod()], it will report an error.
    // For non-interface types T or *T, return the type and function of the method
    The first parameter is the receiver's function.
    // For the interface type, return the provider of the method's type field
	// Returns a Method type by reflecting the type of Method through the integer index
	Method(int) Method

	// Determine whether the type has a method by its name, and return the method if it does, with the ok value true
	MethodByName(string) (Method, bool)

	// Returns the number of externally callable methods that this type has (method names that begin with an uppercase letter)
	NumMethod() int

	// Return the name of the type, or if it is an anonymous type, return null character.
    // If it is array, slice, Map, pointer, etc., then nothing
	Name() string

	// The path to the package where the type is returned, or nothing if it is a pointer
	PkgPath() string

	// Returns the number of bytes required for storage
	// A value of the given type; Similar to unsafe.sizeof.
	Size() uintptr

	// Returns a string representation of the type.
    // String indicates that shortened package names can be used (e.g., base64 instead of "encoding/base64")
	String() string

	Struct,slice, PTR,func, etc.
	Kind() Kind

	// Check whether the type implements the u interface. Note that u must not be nil and is an interface
	Implements(u Type) bool

	// Check whether the type can be assigned to u
	AssignableTo(u Type) bool

	// Determine whether a value of this type can be converted to u
	ConvertibleTo(u Type) bool

	// Determine whether values of this type are comparable.
	Comparable() bool

    // Methods only work for certain types, depending on the type
    // Each method allows:
	//
	//	Int*, Uint*, Float*, Complex*: Bits
	//	Array: Elem, Len
	//	Chan: ChanDir, Elem
	//	Func: In, NumIn, Out, NumOut, IsVariadic.
	//	Map: Key, Elem
	//	Ptr: Elem
	//	Slice: Elem
	//	Struct: Field, FieldByIndex, FieldByName, FieldByNameFunc, NumField
    // Returns the size (in bits) used by the reflection type, causing panic if it is not an Int,Uint,Float, or complex type
	Bits() int

	// Returns the directory of the reflected channel, with an exception if the type is not chan
	ChanDir() ChanDir

	// Check whether the function has variable arguments (...)
	IsVariadic() bool

    //Elem specifies the element type of the return type.
    // Panic occurs if the type of the type is not Array, Chan, Map, Ptr, or Slice.
	Elem() Type

	// Returns the ith field of the structure type. The value is of type StructField
    // If the type of a type is not a Struct, it panics.
    // It will panic if it is not in the range of [0, NumField ()].
	Field(i int) StructField

	// Returns the corresponding nested field
    // If the type of a type is not a Struct, it panics.
	FieldByIndex(index []int) StructField

    FieldByName returns a structure field with the given name
    // And a Boolean value indicating whether the field was found.
	FieldByName(name string) (StructField, bool)

	FieldByNameFunc returns a structure field with a name and a Boolean value indicating whether the field was found
    //FieldByNameFunc considers fields in the structure itself, then any fields embedded in the structure, in width-first order,
    // Stop at the shallowest nesting depth, containing one or more fields that satisfy the matching function.
	FieldByNameFunc(match func(string) bool) (StructField, bool)

    // Returns the type of the ith input parameter of the function type.
    // If the type of the type is not Func, it panics.
    // If I am not in the range of [0, NumIn()], it will panic.
	In(i int) Type

    // Reflect the key type of map type, if not map will generate panic
	Key() Type

	// Returns the length of the reflection array type. If it is not array, panic is generated
	Len() int

	// Return the number of fields reflected in a struct, if not a struct will generate panic
	NumField() int

	// The number of input arguments that reflect a func, if not a function, will generate panic
	NumIn() int

	//NumOut returns a count of the output parameters of the function type.
    // If the type of the type is not Func, it panics.
	NumOut() int

	//Out returns the type of the ith output parameter of the function type.
    // If the type of the type is not Func, it panics.
    // If I am not in the range of [0, NumOut (), it will panic.
	Out(i int) Type

    // Returns the *rtype structure, which is a common implementation of most numeric values.
    // It is embedded in other structure types.
	common() *rtype

    // Returns the *uncommonType type, which exists only in defined types or types with methods
    // unmontypes of T and *T have methods if T is a defined type.
    // Use Pointers to this structure to reduce the overall size required
    // Describes undefined types with no methods.
	uncommon() *uncommonType
}
Copy the code

4.2 the Method structure

MethodByName() and Method() return this type, structured as follows

type Method struct {
	Name    string  //Name is the method Name.
	PkgPath string  // The path to the method

	Type  Type  // Method type
	Func  Value // Take the receiver as the first argument
	Index int   // Method index
}
Copy the code

4.3 StructField structure

Field() and FieldByIndex(), as well as FieldByName(), which FieldByNameFunc returns

// Describe a single field in the structure.
type StructField struct {
	Name string         // Field name
	PkgPath string      // The path of the field in the structure, qualifying the package path of the field name (not reported) starting with a lowercase letter. The package path starting with an uppercase letter is empty.
	Type      Type      // Reflect Type object for the field itself.Type is reflect.Type
	Tag       StructTag // Field label string
	Offset    uintptr   // Offset in structure (bytes)
	Index     []int     // The index sequence of type. FieldByIndex
	Anonymous bool      // Whether the field is anonymous
}
Copy the code

4.4 Introduction to Type Functions

// Return channel type
func ChanOf(dir ChanDir, t Type) Type

// Return Map type
func MapOf(key, elem Type) Type

// Returns the pointer type
func PtrTo(t Type) Type

// Return slice
func SliceOf(t Type) Type

// Reflect variable types, preferably do not pass directly into the pointer. Otherwise something won't launch. For example, the Name ()
func TypeOf(i interface{}) Type
Copy the code
// Examples are as follows
type Student struct {
	User User
	Name string
	Age  string
}

type User struct {
	UserName string
	Password string
	Address string
}

func main (a){
	stu:=Student{
		User: User{
			UserName: "ourlang",
			Password: "123456",
			Address:  "Chengdu",
		},
		Name: "Fu Xiao Lin",
		Age:  "18",
	}
	typeOf := reflect.TypeOf(stu)
	// Return the second stu field Name
	//{Name string 48 [1] false}
	fmt.Println(typeOf.FieldByIndex([]int{1}))
	// Return the second stu field Name because Name is not a struct
	//panic: reflect: Field of non-struct type
	/ / FMT. Println (typeOf. FieldByIndex (int [] {1, 0}))

	// Return the first field UserName in the User structure of stu
	//{UserName string 0 [0] false}
	fmt.Println(typeOf.FieldByIndex([]int{0.0}))
	// Return Address, the third field in the User structure of the first field of stU
	//{Address string 32 [2] false}
	fmt.Println(typeOf.FieldByIndex([]int{0.2}}))Copy the code

4.5 Type Example 1

::: Tip

  • Func TypeOf(I interface{}) Type //Type is an alias for interface{}

  • Array, slice, Map, pointer, etc. Name() returns null.

  • Elem() returns the element type of the type, and panic occurs if the type is not Array, Chan, Map, Ptr, or Slice.

    : : :

package main

import (
	"fmt"
	"reflect"
)
type myInt int64

type User struct {
	UserName string `json:"userName"`
	Password string `json:"password"`
	Age      int    `json:"age"`
	Address  string `json:"address"`
	flag     bool   `json:"flag"`
}

Func TypeOf(I interface{}) Type //Type is an alias of interface{}

// Get the type and kind of data
func GetReflectType(x interface{}) {
	t := reflect.TypeOf(x)
	// Pay special attention to: array, slice, Map, pointer, etc. Name() returns null.
	fmt.Printf("type:%v kind:%v\n", t.Name(), t.Kind())
}

func main(a) {
	var a *float32 / / pointer
	var b myInt    // Custom type
	var c rune     // Type alias
	GetReflectType(a) // type: kind:ptr
	GetReflectType(b) // type:myInt kind:int64
	GetReflectType(c) // type:int32 kind:int32
	u1 := User{
		UserName: "Fu Xiao Lin",
		Password: "123456",
		Age:      28,
		Address:  "Chengdu",
		flag:     true,
	}
	GetReflectType(u1) //type:User kind:struct
}
Copy the code

4.6 Type Example 2

With reflect.StructField, reflect.Method, reflect.Type and other related methods for example, please refer to the article 4-1 Type interface Method summary, 4-2-method structure, 4-3-structfield structure for more types

package main

import (
	"fmt"
	"reflect"
)

type User struct {
	UserName string `json:"userName"`
	Password string `json:"password"`
	Age      int    `json:"age"`
	Address  string `json:"address"`
	flag     bool   `json:"flag"`
}

// Get the type and kind of data
func GetReflectType(x interface{}) {
	t := reflect.TypeOf(x)
	// Pay special attention to: array, slice, Map, pointer, etc. Name() returns null.
	fmt.Printf("type:%v kind:%v\n", t.Name(), t.Kind())
}

func (u *User) GetPassword(a) string {
	return u.Password
}

func (u User) Say(msg string) {
	fmt.Println(u.UserName + msg)
}

func main(a) {
	u1 := User{
		UserName: "Fu Xiao Lin",
		Password: "123456",
		Age:      28,
		Address:  "Chengdu",
		flag:     true,
	}

	stuType := reflect.TypeOf(u1) // Get the type of the structure
	// The number of methods of this type
	numMethod := stuType.NumMethod()
	for i := 0; i < numMethod; i++ {
		// You can also use MethodByName to find a method for a type
		//method, b := stuType.MethodByName("Say")
		myMethod := stuType.Method(i)
		// Method name method type method takes the receiver as the first parameter
		fmt.Println(myMethod.Name, myMethod.Type, myMethod.Func)
	}

	GetReflectType(u1) //type:User kind:struct
	// If u1 is a structure pointer, then decouple elem() or panic occurs
	//numField := stuType.Elem().NumField()
	numField := stuType.NumField()
	for i := 0; i < numField; i++ {
		// You can also use FieldByName to find the corresponding structure field
		//structField, b := stuType.FieldByName("UserName")

		// If u1 is a structure pointer, then decouple elem() or panic occurs
		//field := stuType.Elem().Field(i)
		field := stuType.Field(i)
		// Field name and field type
		fmt.Println(field.Name, field.Type)
		// Whether the field is anonymous and the index position in the structure
		fmt.Println(field.Anonymous, field.Index)
		// The offset (bytes) and the field label string in the structure
		fmt.Println(field.Offset, field.Tag)
		// The path of the field in the structure, qualifying the package path of the field name (not reported) starting with a lowercase letter. The package path starting with an uppercase letter is empty.
		// Only the flag field has the package path
		fmt.Println(field.PkgPath)
	}

}
Copy the code

May reflect the Value explanation

5.1 Method of Value structure

// Usually used to get a pointer to a struct field or slice element. In order to call a method, a pointer receiver is required.
func (v Value) Addr(a) Value

// Returns the underlying value, panic occurs if kind of v is not bool
func (v Value) Bool(a) bool

// Returns the underlying value, and panic occurs if the underlying value of v is not a byte slice
func (v Value) Bytes(a) []byte

// Check if v is addressable
func (v Value) CanAddr(a) bool

// Check if values can be set. Only addressable values can be set
func (v Value) CanSet(a) bool
		
// The reflection function value. And call the
func (v Value) Call(in []Value) []Value

/ / with the Call
func (v Value) CallSlice(in []Value) []Value

// Close the channel, if not Chan then panic
func (v Value) Close(a)

// Returns the underlying value. If the value is not a complex number, a panic is generated
func (v Value) Complex(a) complex128

// returns the value contained in v, mostly used for addressing operations when setting values
func (v Value) Elem(a) Value

// Returns the Value of the index field in the structure
func (v Value) Field(i int) Value

// As above, however, a slice is provided
func (v Value) FieldByIndex(index []int) Value

// Find the value in the structure by the field name
func (v Value) FieldByName(name string) Value

// Search by function name
func (v Value) FieldByNameFunc(match func(string) bool) Value

// Returns the underlying value, generating a panic if the value is not a float
func (v Value) Float(a) float64

// Panic occurs if kind is not array or sliece and returns the element as Value
func (v Value) Index(i int) Value

// Returns the underlying value, or a panic if the value is not an int
func (v Value) Int(a) int64

// Return true if the interface can be used
func (v Value) CanInterface(a) bool

// return V as the current value of interface{}
func (v Value) Interface(a) (i interface{})

// Panic occurs if kind is not an interface
func (v Value) InterfaceData(a) [2]uintptr

// Return value nil. Panic occurs when the value type is not a channel, function, interface, map, pointer, or slice, similar to the v== nil operation at the language level
func (v Value) IsNil(a) bool

// Check whether the value is valid. Returns false if the Value itself is illegal, such as Reflect Value contains no Value, Value nil, etc.
func (v Value) IsValid(a) bool

// return the type of v
func (v Value) Kind(a) Kind

// Return the length of v
func (v Value) Len(a) int

// If it is a map, reflect the Value of its key based on the key
func (v Value) MapIndex(key Value) Value

// Return all keys of the map
func (v Value) MapKeys(a) []Value

// Reflect the value of a method by index
func (v Value) Method(i int) Value

// Count the number of struct methods
func (v Value) NumMethod(a) int

// Reflect method values according to method names
func (v Value) MethodByName(name string) Value

// Reflect the number of fields in a structure
func (v Value) NumField(a) int

// override the complex number
func (v Value) OverflowComplex(x complex128) bool

// Overwrite floating point numbers
func (v Value) OverflowFloat(x float64) bool
func (v Value) overflowFloat32(x float64) bool
func (v Value) OverflowInt(x int64) bool
func (v Value) OverflowUint(x uint64) bool

// reflect the value of a pointer. Returns the integer value of a pointer
func (v Value) Pointer(a) uintptr

// Used for channel reception
func (v Value) Recv(a) (x Value, ok bool)

// Used for channel sending
func (v Value) Send(x Value)

// If v can be set, set a value of v
func (v Value) Set(x Value)

// If v is settable and bool, set a value of v
func (v Value) SetBool(x bool)
func (v Value) SetBytes(x []byte)
func (v Value) SetComplex(x complex128)
func (v Value) SetFloat(x float64)
func (v Value) SetInt(x int64)
func (v Value) SetLen(n int)
func (v Value) SetMapIndex(key, val Value)
func (v Value) SetUint(x uint64)
func (v Value) SetPointer(x unsafe.Pointer)
func (v Value) SetString(x string)
func (v Value) Slice(beg, end int) Value

// Returns the value if the underlying layer is slice.
func (v Value) String(a) string

// If the bottom is a string. Returns a string
func (v Value) TryRecv(a) (x Value, ok bool)

// For channel, accept
func (v Value) TrySend(x Value) bool

// For channel, send
func (v Value) Type(a) Type

/ / return type
func (v Value) Uint(a) uint64

// Return Uint if the underlying layer is Uint
func (v Value) UnsafeAddr(a) uintptr
Copy the code

5.2 Initial Experience of the Value Method

package main

import (
	"fmt"
	"reflect"
)

func GetReflectValue(x interface{}) {
	v := reflect.ValueOf(x) //reflect.Value
	k := v.Kind()           // Get the value category
	switch k {
	case reflect.Int64:
		// v.nt () takes the original value of the integer from reflection and casts it through int64()
		fmt.Printf("type is int64, value is %d\n".int64(v.Int()))
	case reflect.Float32:
		// v.float () takes the original floating-point value from reflection and casts it via float32()
		fmt.Printf("type is float32, value is %f\n".float32(v.Float()))
	case reflect.Float64:
		// v.float () takes the original floating-point value from reflection and casts it via float64()
		fmt.Printf("type is float64, value is %f\n".float64(v.Float()))
	}
}
func main(a) {
	var a float32 = 3.14
	var b int64 = 100
	GetReflectValue(a) // type is float32, value is 3.140000
	GetReflectValue(b) // type is int64, value is 100
	// Convert the original Value of type int to reflect.Value
	c := reflect.ValueOf(10)
	fmt.Printf("type c :%T\n", c) // type c :reflect.Value
}
Copy the code

5.3 Value Modifies the target object

::: tip Pay special attention

  • ValueOf()Pass in the address of a variable and return the address of the variable
  • Function arguments pass copies of values. You must pass the address of the variable to change its value.
  • The Elem() method is used in reflection to get the corresponding value of a pointer, such as a structureReflect.valueof (& variable name).elem ()

: : :

package main

import (
	"fmt"
	"reflect"
)

type User struct {
	UserName string `json:"userName"`
	Password string `json:"password"`
	Age      int    `json:"age"`
	Address  string `json:"address"`
	flag     bool   `json:"flag"`
}

func main(a) {
	u1 := User{
		UserName: "Fu Xiao Lin",
		Password: "123456",
		Age:      28,
		Address:  "Chengdu",
		flag:     true,
	}

	str := "hello world"
	//1 Change the common type
	reflect.ValueOf(&str).Elem().SetString("Zhang")
	fmt.Println(str) / / zhang SAN

	//2 Modify the structure
	//2.1 ValueOf() passes in the address of a variable and returns the address of the variable
	userValue := reflect.ValueOf(&u1)
	//reflect.Value &main.User{UserName:" foo ", Password:"123456", Age:28, Address:" foo ", flag:true}
	fmt.Printf("%T %#v\n", userValue, userValue)
	//2.2 Elem() : returns the original value of the variable
	elem := userValue.Elem()
	//reflect.Value main.User{UserName:" foo ", Password:"123456", Age:28, Address:" foo ", flag:true}
	fmt.Printf("%T %#v\n", elem, elem)
	//2.3 Using FieldByName() : Pass in the structure field name SetString(): Pass in the variable value you want to modify
	elem.FieldByName("UserName").SetString("Bill")
	elem.FieldByName("Age").SetInt(19)
	elem.FieldByName("Password").Set(reflect.ValueOf("admin"))
	fmt.Println(u1) //{admin 19 chengdu true}
}
Copy the code

5.4 Dynamically Invoking methods

: : : tip

  • 1. Call with no arguments
    • ValueOf(variable name).methodByName (method name).call ([] reflect.value {})
    • Call(make([] reflect.value, 0))
  • 2. Call with arguments
    • Call([] reflect.value {reflect.valueof (” first argument “), reflect.valueof (” second argument “)})
  • [] reflect.value {} 3, reflection calls struct methods must be public, reflection calls without arguments must pass nil or [] reflect.value {}

: : :

package main

import (
	"fmt"
	"reflect"
)

type User struct {
	Name     string `json:"name"`
	UserName string `json:"userName"`
	Password string `json:"password"`
	Age      int    `json:"age"`
	Address  string `json:"address"`
	flag     bool   `json:"flag"`
}

func (u User) Say(a) {
	fmt.Println(u.Name + "Speak.")}func (u User) Eat(food string) {
	fmt.Println(u.Name + "The food is." + food)
}

func (u User) Entertain(otherName string, food string) {
	fmt.Println(u.Name + "Please" + otherName + "Eat" + food)
}

func main(a) {

	u1 := User{
		Name:     "Fu Xiao Lin",
		UserName: "ourlang",
		Password: "123456",
		Age:      10,}// No argument method call
	reflect.ValueOf(&u1).MethodByName("Say").Call([]reflect.Value{})       // Kobayashi spoke
	reflect.ValueOf(u1).MethodByName("Say").Call(make([]reflect.Value, 0)) // Kobayashi spoke

	// There are parameter method calls, pay attention to the order
	reflect.ValueOf(u1).MethodByName("Eat").Call([]reflect.Value{reflect.ValueOf(The word "apple")})                               // Kobayashi eats apples
	reflect.ValueOf(u1).MethodByName("Entertain").Call([]reflect.Value{reflect.ValueOf("An Ling Yang"), reflect.ValueOf("Steak")}) // Fu Xiaolin invited Ling Yang to eat steak
}
Copy the code

5.5 Get the wrapped value from the reflection value object

Reflection can not only get the type information of a value, but also dynamically get or set the value of a variable. The Go language uses reflect.Value to get and set the Value of a variable.

Variables, interface{}, and reflect.Value can be converted to each other. As is shown in

package main

import (
	"fmt"
	"reflect"
)

func main(a) {
	// Declare the string variable STR and assign an initial value
	str := "helloWorld"
	// Get the reflection value object of the variable STR
	strValue := reflect.ValueOf(str)
	// Get a value of type interface{}
	strInterface := strValue.Interface()
	// Prints the corresponding type
	fmt.Printf("%T %T \n", strValue, strInterface) //reflect.Value string
	// Convert to string via type assertion
	conStr := strInterface.(string)
	fmt.Printf("%T %+v \n", conStr, conStr) //string helloWorld

	fmt.Println(strInterface) //helloWorld
}
Copy the code

5.6 Determine whether the reflection value is null and valid

IsNil() and IsValid() — Determines whether a reflected value is null or valid. This is especially useful when struct field assignments

package main

import (
	"fmt"
	"reflect"
)

type User struct {
	Name     string `json:"name"`
	UserName string `json:"userName"`
	Password string `json:"password"`
	Age      int    `json:"age"`
	Address  string `json:"address"`
	flag     bool   `json:"flag"`
}

func (u User) Say(a) {
	fmt.Println(u.Name + "Speak.")}func main(a) {
	//* a null pointer to int
	var a *int
	fmt.Println("var a *int:", reflect.ValueOf(a).IsNil())
	/ / nil value
	fmt.Println("nil:", reflect.ValueOf(nil).IsValid())
	//* a null pointer of type int
	fmt.Println("(*int)(nil):", reflect.ValueOf((*int) (nil)).Elem().IsValid())
	// Instantiate a structure
	u1 := User{
		Name:     "Fu Xiao Lin",
		UserName: "ourlang",
		Password: "123456",
		Age:      10,}// Try to find a nonexistent field from the structure
	fmt.Println("Non-existent structure member :", reflect.ValueOf(u1).FieldByName("").IsValid())

	// Try to find a method from the structure that does not exist
	fmt.Println("Methods that do not exist :", reflect.ValueOf(u1).MethodByName("").IsValid())
	fmt.Println("Existing method Say():", reflect.ValueOf(u1).MethodByName("Say").IsValid())

	// Check whether the Name field exists, and then want to modify the corresponding field value
	byName := reflect.ValueOf(u1).FieldByName("Name")
	if byName.IsValid() {
		reflect.ValueOf(&u1).Elem().FieldByName("Name").SetString("Crayon Shin.")
	}

	fmt.Println(u1)

	// Instantiate a map
	m := map[int]int{}
	// Try to find a nonexistent key from the map
	fmt.Println("Non-existent key :", reflect.ValueOf(m).MapIndex(reflect.ValueOf(3)).IsValid())
}
Copy the code

Structural reflection

After any value is reflected through reflect.typeof (), the details of the members of the structure can be obtained through the NumField() and Field() methods of the reflect.type object if its Type is a structure.

The methods in reflect.Type that relate to retrieving a structure member are shown in the following table

methods instructions
Field(i int) StructField Based on the index, returns information about the structure field corresponding to the index.
NumField() int Returns the number of struct member fields.
FieldByName(name string) (StructField, bool) Returns information about the struct field corresponding to the string based on the given string.
FieldByIndex(index []int) StructField Returns field information based on the field index of each structure provided by []int.
FieldByNameFunc(match func(string) bool) (StructField,bool) Match the required fields according to the matching function passed in.
NumMethod() int Returns the number of methods in the method set of this type
Method(int) Method Returns the i-th method in the method set of this type
MethodByName(string)(Method, bool) Returns a method in the method set of that type based on the method name
## 7 Reflection example
“`go
package main

import ( “fmt” “reflect” )

type Call struct { Num1 int Num2 int }

Func (call call) GetSub(name string) {fmt.printf (“%v %v – %v = %v \n”, name, call.Num1, call.Num2, call.Num1-call.Num2) }

Func (call * call) GetSum(name string) {fmt.printf (“%v %v + %v = %v \n”, name, call.Num1, call.Num2, call.Num1+call.Num2) }

func main() { var ( call *Call rValues []reflect.Value rValues2 []reflect.Value ) ptrType := reflect.TypeOf(call) // Get the reflect.type of the call pointer

TrueType := ptrtype.elem () // get the trueType of type ptrValue := reflect.new (trueType) // return the pointer to the object corresponding to reflect.value call = Ptrvalue.interface ().(*Call) trueValue := ptrValue.elem () // Get the true structure type truevalue.fieldByName ("Num1").setint (123) // Set object properties, // ptrValue.fieldByName ("Num2").setint (23) trueValue.FieldByName("Num2").SetInt(23) //rValues = make([]reflect.Value, 0) rValues = append(rValues, Reflect.valueof ("xiaopeng")) // Call the corresponding method fmt.println (rValues) trueValue.MethodByName("GetSub").call (rValues) /* fixme In reflection, pointer methods cannot be called to the actual type, and methods of the actual type can be called to the pointer type, */ / ptrValue.methodByName ("GetSub").call (rValues) //trueValue.MethodByName("GetSum").Call(append(rValues2, reflect.ValueOf("hiram"))) ptrValue.MethodByName("GetSum").Call(append(rValues2, Reflect.valueof (" Hiram "))) fmt.println (call) /* Fixme in practice, Pointers and entities can be converted to each other without affecting the call. GetSub("aaa") (*call).getSub (" BBB ") Call.getSum (" CCC ") (*call).getSum (" DDD ")Copy the code

}

The common application scenarios of reflection are as follows: - 1 Do not know which function is called on the interface, and determine the specific interface to be called according to the passed parameters at run time. This requires reflection on the function or method. For example, go func bridge(funcPtr interface{}, args... interface{})Copy the code
  • The type of argument passed to the function is not known. The function needs to process arbitrary argument objects at run time, which needs to be reflected on the structure object. The typical application scenario is ORM. The following is an example of GORM:
type User struct {
  gorm.Model
  Name         string
  Age          sql.NullInt64
  Birthday     *time.Time
  Email        string  `gorm:"type:varchar(100); unique_index"`
  Role         string  `gorm:"size:255"` // set field size to 255
  MemberNumber *string `gorm:"unique; not null"` // set member number to unique and not null
  Num          int     `gorm:"AUTO_INCREMENT"` // set num to auto incrementable
  Address      string  `gorm:"index:addr"` // create index with name `addr` for address
  IgnoreMe     int     `gorm:"-"` // ignore this field
}
 
var users []User
db.Find(&users)
Copy the code

9 Reference Materials

Golang. Google. Cn/PKG/reflect…

golangbot.com/reflection/