Use of reflection in the Go language

Source: Internet
Author: User
Tags switch case
This is a creation in Article, where the information may have evolved or changed.

I tried today. Using reflection in the go language to convert a struct type to XML is a pretty tangled result. First go to see the implementation of go reflect package, according to go rules, first should go to see a newxxx method, the result found a method called NewValue, through this method we can get a value interface. In addition, we should note that the reflection implementation of go separates the type and value, so there is another interface type.

  Type value interface {//type returns the value ' s type.    Type () type//Interface returns the value as an interface{}.    Interface () interface{}//Canset returns whether the value can be changed.    Values obtained by the non-exported struct fields//can is used in Get and not Set.    If Canset () returns false, calling the Type-specific Set//would cause a crash. Canset () bool//SetValue assigns v to the value;    V must has the same type as the value.    SetValue (v Value)//ADDR Returns a pointer to the underlying data.    It is for Advanced Clients that also//import the "unsafe" package.    ADDR () UIntPtr//method returns a funcvalue corresponding to the value ' s i ' th method. The arguments to a call in the returned Funcvalue//should not include a receiver;    The funcvalue would use//the value as the receiver. Method (i int) *funcvalue//contains unexported Methods}type type interface {//Pkgpath returns THE type ' s package path.    The package path was a full package import path like "Container/vector".    Pkgpath returns a empty string for unnamed types.    Pkgpath () string//Name returns the type ' s name within its package.    Name returns a empty string for unnamed types.    Name () string//String returns a string representation of the type.     The string representation shortened package names//(e.g., vector instead of "container/vector") and was not  Guaranteed to be unique among types.    To test for equality,//compare the Types directly. String () string//Size Returns the number of bytes needed to store//a value of the given type; It's analogous to unsafe.    Sizeof.    Size () uintptr//Bits returns the size of the type in Bits.    It is intended for use with numeric types and may overflow//when used for composite types. Bits () int//Align Returns the alignment of a value of this type//when allocated in memory.    Align () int//Fieldalign Returns the alignment of a value of this type/when used as a field in a struct.    Fieldalign () int//Kind returns the specific Kind of this type.    Kind () Kind//For Non-interface types, method returns the I-th method with receiver T.    For interface types, method returns the I ' th method in the interface.    Nummethod returns the number of such methods. Method (int) method Nummethod () int//contains unexported methods}

Then the package also defines the corresponding Xxxtype and Xxxvalue structures based on each data type, so how do we get examples of these structures? Because only instances of these bodies can use reflection to manipulate the data. So the ugly place is coming, you need to use. (type) to get the current type of the variable, and this use must be in switch, see the example below

func test(data interface{}) {    switch rvalue := reflect.NewValue(data).(type) {    default:        println(reflect.Typeof(rvalue).String())    }       switch rtype := reflect.Typeof(data).(type) {    default:        println(reflect.Typeof(rtype).String())    }       switch rvalue := data.(type) {    default:        println(reflect.Typeof(rvalue).String())    }   }

NewValue created a value interface for data, but who does this interface? Pass. (type) can be obtained.

typeof creates a type interface for data, and the same interface can be passed. (type) to get its implementation.

If you do not use any of the methods in reflect to directly use the variable data. (type), you will get the implementation of this interface.

So from here we can see that the use of the go language reflects the need for two conditions, one through the type to get its implementation variables, one is through the interface provided by the reflect to operate.


But it's disgusting that every operation has to be done through a switch case, such as my Code at the end of the following:

Func asstring (Val interface{}) string {switch value: = Reflect. NewValue (Val). (type) {Case *reflect. Stringvalue:return value. Get () Case *reflect. Boolvalue:return StrConv. Btoa (value. Get ()) Case *reflect. Intvalue:return StrConv. Itoa64 (value. Get ()) default:panic ("Invalid type for XML generator")}return ""}func toXml (Val interface{}, writer Io. Writer) {switch value: = Reflect. NewValue (Val). (type) {Case *reflect. Structvalue:writer. Write ([]byte ("<")) writer. Write ([]byte (reflect. Typeof (Val). Name ())) switch VType: = reflect. NewValue (Val). Type (). (type) {Case *reflect. Structtype://compose attributefor I: = 0; I < value. Numfield (); i++ {field: = VType. field (i) if field. Tag! = "attr" {continue}writer. Write ([]byte (")") writer. Write ([]byte (field. Name)) writer. Write ([]byte ("=/")) writer. Write ([]byte (Asstring (value. Field (i). Interface ())) writer. Write ([]byte ("/"))}writer. Write ([]byte (">"))//compose childrenfor I: = 0; I < value. Numfield (); i++ {field: = VType. field (i) if field. Tag = = "attr" {ContinUe}switch Child: = value. Field (i). (type) {Case *reflect. Structvalue:toxml (child. Interface (), writer) case *reflect. Arrayvalue:case *reflect. Slicevalue:writer. Write ([]byte ("<")) writer. Write ([]byte (field. Name)) writer. Write ([]byte (">")) for I: = 0; I < child. Len (); i++ {switch Elem: = child. Elem (i). (type) {Case *reflect. Structvalue:toxml (Elem. Interface (), writer) default:panic ("Invalid type for array, only struct supported")}}writer. Write ([]byte ("
  ")) Default:writer. Write ([]byte (Asstring (child. Interface ()))}}//compose Endwriter. Write ([]byte ("
  ")) Default:panic (" Invalid type:only array, slice, struct and primitive type supported ")}default:panic (" Invalid type, onl y struct supported ")}}
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.