Understanding Golang Reflection (reflection in Go)

Source: Internet
Author: User

Reflection (reflection) refers to the ability to dynamically acquire program structure information (meta-information) at run time, which is a feature supported by static type languages such as Java, Golang, and so on. Here is a detailed introduction of Golang reflection related knowledge

Type and interface (Types and interfaces)

Type MyInt Intvar i intvar J MyInt

I is of type int, J is Myint type. Although the i,j underlying types are int, they are of different types and no conversions can be assigned to each other.

Interface type interface, which represents a collection of methods, any concrete (non-interface) value can be assigned to interface as long as the interface method is implemented

Reader is the interface that wraps the basic Read Method.type Reader Interface {Read (P []byte) (n int, err error)}/ /writer is the interface that wraps the basic Write method.type Writer Interface {write (P []byte) (n int, err error)} var r io. Readerr = OS. Stdinr = Bufio. Newreader (r) r = new (bytes. Buffer)//And so on

The static type of the R variable is IO. Reader, the actual type may be file, buffer type

interface{} Special interface type, there is no method, so any type can be assigned to it

The representation of an interface

var r io. Readerr = new (bytes. Buffer)

The specific type of r variable is IO. Reader, the actual type is bytes. Buffer, how is Golang implemented at run time?

A variable of type interface stores 2 information, a value, type pair <value,type> pair:

    • The value assigned to the variable (concrete value)

    • Type descriptor for variable value (value' s type descriptor)

var r io. Readertty, err := os. OpenFile ("/dev/tty",  os. o_rdwr, 0) if err != nil {    return nil, err}r =  tty 

interface type R <value, type> pair is ( tty ,   *os. File ) /span>

Of course the value TTY of the R variable does not only implement IO. The Read method in the reader interface also implements IO. Write method in writer, so you can do

Type assertion, which attempts to convert R to IO. Writer

var w io. Writerw = R. (IO. Writer)

At this point, the <value,type>pair of the interface variable w is ( tty , *os.File ), that is, r,w the underlying value is the same, you can expose different methods by different type.

Continue discussion

var empty interface{}empty = w//The type assertion is not required here, because any type can be considered as a way to implement the empty interface

Interface variable empty <value,type> pair for ( tty , *os.File )

Reflection

1. Reflection goes from interface value to Reflection object. (Interface type---> Reflection type (reflect. Value,reflect. Type))

Reflection, you can get specific information about the interface type variable (<value,concrete type>)

Golang Reflector Package for reflect

ValueOf returns a new Value initialized to the concrete value//stored in the interface I. ValueOf (NIL) returns the Zer  o value.func ValueOf (i interface{}) Value//Get pair value//TypeOf returns the reflection Type that represents the dynamic Type of i.//If i is a nil interface value, TYPEOF returns Nil.func TypeOf (i interface{}) type//Get concrete type in pair

eg

var r io. Readerr = OS. Stdin//<value, type>: <os. Stdin, *os. File>rvalue: = reflect. ValueOf (r) Rtype: = reflect. TypeOf (R) fmt. Println ("Value:", RValue) fmt. Println ("type:", Rtype) Output: value: &{0xc04205a000}//pointer type: *os. Filevar f float64f = 1.234fmt. Println ("F Value:", reflect. ValueOf (f)) fmt. Println ("F Type:", reflect. TypeOf (f)) output: F value:1.234f type:float64

2. Reflection goes from Reflection object to interface value. Reflection type (reflect. Value,reflect. Type)--Interface types

Type user struct {   id   int   name string    Age  int}func  (U user)  reflectcallfunc ()  {    Fmt. Println ("Reflect learn")}user := user{1,  "test",  13}var i interface{}i  = useruvalue := reflect. ValueOf (i) utype  := reflect. TypeOf (i) fmt. Println ("uvalue: ", Uvalue) fmt. The Println (Uvalue.interface ())  //is converted to the Interface type, Unpack uvalue.interface (). (User) fmt. Println (Uvalue.type ()) fmt. Println ("uvalue,string: ", Utype.string ()) fmt. Println ("utype: ", Utype.name ()) For i := 0; i < utype.numfield ();  i+ + { //get field Information    field := utype.field (i)    value :=  uvalue.field (i). Interface ()    fmt. Printf ("%s: %v = %v\n",  field. Name, field. Type, value)}for i : = 0; i < utype.nummethod (); i++ {//  Get method information    method  := utype.method (i)     fmt. Printf ("method[%d] = %s \n", I,method. Name)}fmt. Println (Uvalue.kind ()) fmt. Println (Utype.kind ())


3. To modify a reflection object, the value must is settable. modifying variables by Reflection

var x float64 = 3.4v: = reflect. ValueOf (x) fmt. Println ("Settability of V:", V.canset ())//print:settability of V:falsev. SetFloat (7.1)//Error:will panic.

Reasons for non-modifiable:we pass a copy ofx toreflect.ValueOf, so the interface value created as the argument toreflect.ValueOfis a copy ofx, notxitself

Workaround, pass the pointer!!

var x float64 = 3.4p: = reflect. ValueOf (&x)//Note:take the address of x.fmt.println ("type of P:", P.type ()) fmt. Println ("Settability of P:", P.canset ()) Print:type of P: *float64settability of P:false//why? P non-set,p points can be set,p point to the content that is *p, how to get p point of content?

Reflect. The Elem method of value that can get the content that the value points to

V: = P.elem () fmt. Println ("Settability of V:", V.canset ())//settability of V:truev. SetFloat (7.1) fmt. Println (V.interface ())//7.1fmt. PRINTLN (x)//7.1


4. Structs Reflection Operation Example

Type T struct {A int B string}t: = t{23, "Skidoo"}s: = Reflect. ValueOf (&t). Elem () Typeoft: = S.type () for I: = 0; I < S.numfield (); i++ {f: = S.field (i) fmt. Printf ("%d:%v%s%s =%v\n", I, S.kind (), Typeoft.field (i). Name, F.type (), F.interface ())}fmt. Println ("Canset:", S.canset ()) S.field (0). Setint (S.field) (1). SetString ("Sunset Strip") fmt. Println ("After Change:", S.interface ())

5. Calling methods via reflect

Type user struct {   id   int   name string    Age  int}func  (U user)  reflectcallfunc ()  {    Fmt. Println ("Reflect learn")}func  (U user)  funchasargs (name string, age int)  {   fmt. Println ("funchasargs name: ", name,  ",  age:", age,  "and origal  User.Name: ",  u.name)}func  (U user)  funcnoargs ()  {   fmt. Println ("Funcnoargs")}user := user{1,  "test",  13}uvalue := reflect. ValueOf (user) Utype  := reflect. TypeOf (user) M1 := uvalue.methodbyname ("Funchasargs") m2 := uvalue.methodbyname ("FuncNoArgs") ) M ,b := utype.methodbyname ("Funcnoargs") args := []reflect. Value{reflect. ValueOf ("Xiong"),  reflect. ValueOf (}M1). Call (args) Args = make ([]reflect. Value,0) m2. Call (args) fmt. Println ("M1:", M1) FMT. Println ("m2:", m2) fmt. Printf ("m:% #v, isfound:%v\n", M,b) fmt. PRINTLN (M1)



Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.