This is a creation in Article, where the information may have evolved or changed.
Catalogue [−]
- Type
- Value
- Transformation
This chapter focuses on reflection in the go language.
Package reflect can implement run-time reflection, allowing the program to manipulate the values and types of objects.
Typically, you can get the dynamic type of interface{} along with its values and methods.
Go is a statically typed language, and each object has a certain value at the time of declaration and initialization, even if it is a variable declared as an interface type, and its static type is determined even if any object of the type containing the interface method set can be assigned to it.
We can get the dynamic type and value of the object at run time.
The types type and value values are the two main concepts we use for the launch library.
Type
Typeis a interface that represents a type in go, which can be viewed as a type of metadata (describing the type of the type), which can be either the go language or the type defined in the library or the type you define yourself.
Here we introduce the main methods and some auxiliary methods.
It is important to note that not all methods are valid for a certain type, for example, some methods only make sense for a function type, and some are only meaningful to structs. If the wrong method is called on a type, the runtime's panic will occur, such as for the struct type, to invoke the IsVariadic method. So it's best to judge the type's kind first.
First we define a simple struct to test for the following example, Bird has three fields and three methods, of which two fields and two methods are exported:
1234567891011121314151617 |
type struct {Name string stringage int}funcstring {return' Sing'} Funcstring {return"Fly"}func (b *bird) food () {} |
TypeOfReturns the dynamic type of an interface object, which is reflect.Type a value of type:
123 |
var "Parrot" "Blue"} var t reflect. Typet = reflect. TypeOf (bird) |
- Name,pkgpath,String
Returns the name of the dynamic type, the package name, and the string representation.
123 |
//bird //main. Bird//main |
Name returns a type name, such as bird, that returns an empty string for a type that does not have a defined name.
Pkgpath returns the package name, which represents the unique identifier of the package, so it may be a single package name, or encoding/base64 . An empty string is returned for the go built-in type String,error, and so on, or the type struct{}, which does not define a name.
The string method returns an expression of this type, and the package name may be in shorthand notation.
- Kind
Returns the classification of the type. The type you define yourself must belong to one of the following categories:
1234567891011121314151617181920212223242526272829 |
Const ( 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) |
For example:
- Size,Bits,Align,fieldalign
12345 |
//40 //fmt. Println (T.bits ()) //panicFMT. Println (T.align ()) //8//8} |
SizeReturns the number of bytes required to store a value of this type, which returns the memory that is required to save the stored value, without calculating the size of the memory it references. For example, a string is StringHeader stored as a type, it contains a pointer to the memory character stored data, its size only calculates the memory required to store the structure, and does not calculate the data that the pointer points to occupy the number of bytes, the data will be aligned.
BitsReturns a size of type, calculated as bit, but panic if the type is not one of int, Uint, Float, complex.
AlginIs the number of bytes used by a variable of this type in memory. FieldAlignrefers to a variable of this type if it is a field in a struct, then it is aligned with the number of bytes used.
The same is true for GC compilers, Align FieldAlign but they may be different for gccgo.
There is also the following reflect.StructField.Offset , which is the offset of a field in a struct, taking into account the alignment of the preceding field.
Why are you aligning?
The first reason-a lot of CPUs just start loading data from the aligned address, and some CPUs do it just a little faster.
The second reason--the external bus gets data from memory one time is not 1byte, but 4bytes maybe 8bytes, or more ~ ~
The intro knows
Note The Size number of bytes that the value occupies, and the Align number of bytes that the variable occupies.
For example, in my current development environment (64-bit Windows 10), the string is Size 16 bytes, and the string is Align 8, the int type Size Align is 8, the Int32 Size and Align both are 4.
- Implements,assignableto,Convertibleto,comparable
ImplementsReturns whether the type implements an interface, or panic if the type of the parameter is not a interface type.
123456 |
var r *io. Readert1: = reflect. TypeOf (R). Elem () t2: = reflect. TypeOf (&os. Stdout). Elem () fmt. Println (t.implements (t1)) //false//true |
AssignableToWhether a value of a type can be assigned to the type specified by the parameter, the pointer object of type bird in the following example can be assigned to the Ibird interface:
1234567 |
type Interface string string} var i ibird = &birdfmt. Println (T.assignableto (reflect. TypeOf (i). Elem ())) |
ConvertibleToWhether a value of one type can be converted to a value of another type:
12345 |
type Bird2 Birdvar//trueBird = Bird (bird2) //can be converted |
ComparableWhether the return type can be compared:
If the type can be compared, the operator can be used == != . You can see the comparison operator.
- Numfield,Field,fieldbyindex,fieldbyname,fieldbynamefunc
This set of methods is used to obtain information about the field of a struct, which is described by the Structfield type. If the type is not a struct, calling the appropriate method causes the runtime to panic.
NumFieldReturns the number of fields for a struct.
FieldReturns information about the I field of a struct, including information about an object that is not exported
123 |
Fmt. Println (T.field(0//{name string 0 [0] false}FMT. Println (T.field(1//{color string [1] false}FMT. Println (T.field(2//{age github.com/smallnest/dive-into-go/ch12/model int [2] false} |
FieldByIndexFor nested structs, you can recursively get information about a layer's fields:
12345678910111213141516 |
type struct string Age int}typestruct {S1}typestruct {S2}var s S3t4: = Reflect. TypeOf (s) fmt. Println (T4. Fieldbyindex ([]int{0, 0, 1//{age int [1] false} |
This example S3 nested s2,s2 nested S1, and we can get the S1 field information by 0,0,1.
FieldByNameGets the field information by name:
1 |
Fmt. Println (T4. Fieldbyname ("Name"//{name string 0 [0 0 0] false} True |
FieldByNameFuncReturns the first field that meets the criteria, based on a function filter field:
1234567 |
Fmt. Println (T4. Fieldbynamefunc (funcstringbool {If"age" {return true} return false})) |
- Nummethod,Method,methodbyname,
This is a set of methods for a set of action types.
For a non-interface type T or *t, its method type and function number fields describe the first parameter of the method is receiver.
For an interface type, the Func field of its method type is always nil.
NumMethodReturns the number of methods in this type of method set, Method returning the information for the I method:
1234567 |
FMT. Println (T.nummethod ()) //1 fmt. Println (T.method (0 )) //{sing func (model. Bird) string <func (model. Bird) string value> 0} T5: = reflect. TypeOf (&bird) fmt. Println (T5. Nummethod ()) //3 fmt. Println (T5. Method (0 )) //{fly func (*model. Bird) string <func (*model. Bird) string value> 0} fmt. Println (T5. Method (1 )) //{sing func (*model. Bird) string <func (*model. Bird) string value> 1} fmt. Println (T5. Method (2 )) //{food github.com/smallnest/dive-into-go/ch12/ Model func (*model. Bird) <func (*model. Bird) value> 2} |
MethodByNameThe lookup method is based on the name.
- numin,in,numout,out,isvariadic
For the function type, we are concerned with its input parameter information Int and output parameter information Out .
IsVariadicReturns whether the function is a variable parameter.
1234567 |
F: = http. Listenandserveft: = reflect. TypeOf (f) fmt. Println (ft. Numin ()) //2fmt. Println (ft. In(0)) //string//1fmt. Println (ft. out (0)) //error//false |
- Key
KeyThe Panic method returns the type of the key of the map type, and if it is not a map type, calling this method will be called.
123 |
var Map [string] intMT: = reflect. TypeOf (m) fmt. PRINTLN (Mt. Key ()) |
- Elem
ElemThe method returns the type of the element of Array, Chan, Map, Ptr, slice.
For the map type, it returns the type of the value.
For pointer-type PTR, it returns the type of the element that the pointer points to.
For Chan, it returns the type of the element being passed.
Arrays and slice return the types of elements that it contains.
Len
LenReturns the length of the array, because the type of the array contains the definition of length. It is panic if it is not an array.
Chandir
Return to channel direction, Chan, chan<-, <-chan
Value
Value describes the values of the object, and not all methods make sense for any type, and the specific method only applies to the specific type.
A value of 0 means that there is no value, it always returns IsValid false, it always returns Kind invalid, and its string always returns " ".
A value can be used concurrently by multiple goroutines provided that the underlying Go Value can is used concurrently for The equivalent direct operations.
Using = = On both values does not compare the underlying values they represent, but rather the contents of the Value structs . To compare, compare the results of the Interface method.
The method for elaborating the value object is not prepared in this article. Not that these methods are unimportant, but that they have too many methods.
It provides a corresponding method for each type of operation, such as slice type, append, Appendslice and other methods, map Mapindex, Mapkeys and other methods, struct has field, fieldbyindex and so on. Note that the field method of value returns the value of the fields as the type of values, rather than the type description type of the field. There are also methods for numerical, bool, channel types, and so on.
IndirectReturns the object that the pointer points to, or the parameter itself if it is not a pointer.
AddrReturns a pointer to an addressable object. The addr method can be called only for slice elements, the elements of an addressable array, the fields of an addressable struct, and the addressable results of pointers. Can be CabAddr checked by. You can view the description in the GO specification: Address operators.
ZeroReturns the 0 value of the type.
A set of SETXXX methods used to set values (good-wrapping).
The following is a set of auxiliary functions that generate a value object:
MakeChan,,,,, MakeFunc MakeMap MakeSlice New NewAt generates the value of a type.
ValueOfReturns value from the interface object.
Transformation
1. From the interface object to the Reflection object
123 |
var float64 = 3.4 FMT. Println ("type:", reflect. TypeOf (x)) fmt. Println ("value:", reflect. ValueOf (x)) |
2. From reflected object to interface object
If you want to convert to a specific type of object, you can use type assertion:
1 |
Y: = V.interface (). (float64) |
3. Modify the Reflection Object
The value of the object must be set and can be judged by the Canset method.
123456 |
var float64 = 3.4P: = reflect. ValueOf (&x) V: = P.elem () v.setfloat(7.1) fmt. Println (V.interface ()) fmt. PRINTLN (x) |
There are also some third-party simplified go reflect libraries, such as Go-reflector.
Reflection is often used in the implementation of serialization and deserialization, such as the official JSON, XML library.
Keep in mind, however, that the performance of the launch is not high, so many of the serialization libraries use code templates to generate model objects instead of reflecting them in a way that serializes and deserializes objects.
Reference
- http://blog.golang.org/laws-of-reflection
- http://golang.org/pkg/reflect/
- /http Research.swtch.com/interfaces
- http://my.oschina.net/tongjh/blog/513540
- http://blog.altoros.com /golang-internals-part-6-bootstrapping-and-memory-allocator-initialization.html
- http://grokbase.com/t/ Gg/golang-nuts/153kv99728/go-nuts-how-to-use-reflect-type-implements