This is the 23rd day of my participation in Gwen Challenge

These reviews

If you don’t already know Go, I suggest you read mineGo from zero.

In this series of articles, I’ll take a closer look at the Go language and introduce advanced features such as package management, reflection, and concurrency. Go reflects. Value, which allows you to view and modify the Value of a variable. This paper will continue to introduce the reflect.Value of Go language through cases, how to judge whether the Value of a variable can be set, and how to call functions.

Reflect. Value Indicates the reflected Value object

For structure-type variables, the fields in the structure must not only be addressable, but must also be exposed to be set. Therefore, the Value#CanSet method can be used to determine whether the Value of a variable can be set. Value also provides #NumField, #FieldByIndex, and #FieldByName values for struct body fields. The following code shows how to set the Value of a struct body field:

hero := &Hero{ Name: "White", } valueOfHero := reflect.valueof (hero).elem () valueOfName := valueofhero.fieldByName ("Name") // Check whether the Value of the field can be set to if Valueofname.canset () {valueofname.set (reflect.valueof ("小张"))} fmt.printf ("hero name is %s", hero.name)Copy the code

The expected results are:

Hero name is Xiao ZhangCopy the code

You can see that the name of hero has been changed to zhang, and an error will be thrown if the Value of the field is not exposed.

In addition to fetching set values, Value can also be used to reflect calls to functions like the following:

func (v Value) Call(in []Value) []Value
Copy the code

The parameter list in []Value represents the reflected method’s parameters. We need to pass the values generated by the method’s parameters to the called method in the declared order. The returned result []Value is also the Value wrapper of the result returned by the method call.

Next we demonstrate an example of how to call a method in the interface, as follows:

Var person person = &hero {Name: "", Speed: In 100, } valueOfPerson := reflect.valueof (person) sayHelloMethod := valueofPerson.hero ("SayHello") // Call([] reflect.value {reflect.valueof (" small ")}) // Get the Run method runMethod := ValueOfPerson. MethodByName (" Run ") / / # Call invoking method and obtain the result the result: = runMethod. Call ([] reflect the Value {}) FMT) Printf (" result of run method is %s.", result[0])Copy the code

The expected output is:

Hello Xiao Zhang, I am Xiao Hong I am running at speed d result of run method is running.Copy the code

In the above code, we declare a Person interface and implement it using the Hero structure, then get the Value object of The Person, then get the Value of the corresponding method using Value#MethodByName (only public methods), Finally, the method is called through the Value#Call reflection. Before calling a method with Value#Call, we build a parameter list of type []reflect.Value, passing the values of the method arguments to the called method in the declared order; At the end of the method call, a [] reflect.value list is returned with the result of the call, so that we can access the result of the method call.

The Value of the above method is obtained directly from the Value of the Person interface, and the method’s receiver Person is passed in by default when the method is called. If the Value of the interface method is not obtained from the Value object of the interface, but from the Type object, etc., then the Value of the latter method needs to be explicitly placed first in the in []Value argument list when called because of the receiver address loss. See the following example:

var person Person = &Hero{ Name: TypeOfPerson := reflect.TypeOf(Person) // Print the Person method type and name sayHelloMethod, _ : = typeOfPerson MethodByName (" Run ") / / put the person receiver on the parameters of the first result: = sayHelloMethod.Func.Call([]reflect.Value{reflect.ValueOf(person)}) fmt.Printf("result of run method is %s.", result[0])Copy the code

Otherwise an exception with too few arguments will be thrown, as shown below:

panic: reflect: Call with too few input arguments
Copy the code

The launch call to the general method is very simple and can be used directly using reflect#ValueOf to get the Value of the method according to the function pointer, as shown in the following example:

func main() { methodOfHello := reflect.ValueOf(hello) methodOfHello.Call([]reflect.Value{}) } func hello() { FMT. Print (" Hello World!" )}Copy the code

summary

This article and the previous article mainly introduced the Go language reflection.Value reflection Value object related content. The next article will begin to introduce the concurrency model, an important feature of the Go language.

Read the latest article, pay attention to the public number: AOHO Qiusuo