This is the 20th day of my participation in the Genwen 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.

The previous articles focused on the application practices of Go package dependency management GOPATH and Go Module. This article will cover the Go reflection.

Reflection basis

Reflection is a powerful tool that gives developers the ability to access and modify the code itself at run time. Next, we introduce the two important concepts of Type and Value in Go reflection.

We first define some simple structure and method of experiment for behind us, the code as shown below, mainly in the feature/relection/reflection. Go under the file:

package main

import "fmt"

// Define a human interface
type Person interface {

	// Say hello to someone
	SayHello(name string)
	/ / running
	Run() string
}

type Hero struct {
	Name string
	Age int
	Speed int
}

func (hero *Hero) SayHello(name string)  {
	fmt.Println("Hello " + name, ", I am " + hero.Name)
}

func (hero *Hero) Run(a) string{
	fmt.Println("I am running at speed " + string(hero.Speed))
	return "Running"
}
Copy the code

In the above code, we define a Person interface and a Hero structure to implement the methods in the Person interface, which also contains three member fields.

The reflection of Go is quite different from that of Java and other languages. It is mainly explained through the two basic concepts of Type and Value. Type is used to represent the Type information of the reflected variable, and Value is used to represent the instance information of the reflected variable itself. The reflection implementation of Go is primarily in the Reflect package.

Reflect. Type Object of Type

Reflect# TypeOf method, we can easily get the Type information for a variable reflect.type. Through an object of Type reflect.Type, we access information about each Type of its corresponding Type. We can create a Hero structure and view its corresponding type information through reflect#TypeOf as follows:

func main(a)  {
	// Get the reflection type object of the instance
	typeOfHero := reflect.TypeOf(Hero{})
	fmt.Printf("Hero's type is %s, kind is %s", typeOfHero, typeOfHero.Kind())

}
Copy the code

The running result is as follows:

Hero's type is main.Hero, kind is struct
Copy the code

In Go, there is a distinction between Type and Kind. As shown in the result above, the Type of Hero is main.Hero and the Type is struct. Type refers to the Type that a variable belongs to, including the system’s native data types such as int, string, etc., and the types we define through the Type keyword, such as the Hero structure we define. The names of these types are usually the types themselves. Kind refers to the variety to which the variable type belongs. Refer to the definition in Reflect. Kind, which mainly includes the following types:

type Kind uint

const (
	Invalid Kind = iota
	Bool
	Int
	Int8
	Int16
	Int32
	Int64
	Uint
	Uint8
	Uint16
	Uint32
	Uint64
	Uintptr
	Float32
	Float64
	Complex64
	Complex128
	Array
	Chan
	Func
	Interface
	Map
	Ptr
	Slice
	String
	Struct
	UnsafePointer
)
Copy the code

Structs are structs defined by the type keyword, and the type of pointer variable is Ptr, as in the following code:

	fmt.Printf("*Hero's type is %s, kind is %s",reflect.TypeOf(&Hero{}), reflect.TypeOf(&Hero{}).Kind())
Copy the code

In the above code, the type object of the Hero pointer is retrieved through reflect#TypeOf, and its output will be:

*Hero's type is *main.Hero, kind is ptr
Copy the code

This shows that &hero {} is of type *main.Helo and belongs to the class PTR. For variables of type pointer, you can use Type#Elem to get the object of the real type that the pointer points to, as shown in the following example:

	typeOfPtrHero := reflect.TypeOf(&Hero{})
	fmt.Printf("*Hero's type is %s, kind is %s\n",typeOfPtrHero, typeOfPtrHero.Kind())
	typeOfHero = typeOfPtrHero.Elem()
	fmt.Printf(" typeOfPtrHero elem to typeOfHero, Hero's type is %s, kind is %s", typeOfHero, typeOfHero.Kind())
Copy the code

The expected output is:

*Hero's type is *main.Hero, kind is ptr
 typeOfPtrHero elem to typeOfHero, Hero's type is main.Hero, kind is struct
Copy the code

TypeOfPtrHero# Elem: *main.Helo: main.Hero: typeOfPtrHero#Elem: *main.Helo: Main.

summary

This article mainly introduces the reflection basis of Go language. Reflection allows us to retrieve rich type information, such as variable field names, type information, and structure information, and use this type information to do some flexible work. Go’s reflection implements most of the functions of reflection, and obtaining type information requires scanning the source code using lexical, syntax parsers, and abstract syntax numbers in the standard library.

The next article will cover reflection in Go.

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