Reflection of methods and types
When reflecting, use the program to check its own structure. Yes meta-programming A form of. Reflection can check types and variables at run time. Unless it is really necessary, it should be avoided or used with care.
Two simple functions in the reflection package:
- reflect. Typeof (I interface {}): returns the type of the checked object
- reflect. Valueof (I interface {}): returns the value of the checked object
var x float64 = 3.14 fmt.Println(reflect.TypeOf(x)) fmt.Println(reflect.ValueOf(x))
Output results:
float64 3.14
In addition, we can use the kind () method to identify reflect The data type returned by valueof(). If the value type of X is float64, then reflect ValueOf(x). Kind( ) == reflect. Float64.
fmt.Printf("%t",reflect.Float64==v.Kind())
Output results:
true
The Kind() method always returns the underlying type.
type MyInt int var myint MyInt = 5 fmt.Println(reflect.TypeOf(myint)) fmt.Println(reflect.ValueOf(myint).Kind())
Output results:
main.MyInt int
You can see reflect. Net from the output result Typeof() returns the type used when the variable is declared, while Kind() returns the underlying type of the type used when the variable is declared.
The restored value can be obtained by using the Interface() method
fmt.Printf("%v,%[1]T\n%v,%[2]T",v,v.Interface()) fmt.Println(v.Interface()==reflect.Float64)
Output results:
3.14,reflect.Value 3.14,float64 false
The Interface() method can set reflect The return Value of the valueof() function is converted from the Value type to the original type. Using Float(), Int(), String(), Bool() and other methods can also achieve the same functions.
fmt.Printf("%v,%[1]T\n",v.Float())
Output results:
3.14,float64
Modify values by reflection
The method of SetFloat() can be used to modify the value. You must be careful when using it. If the variable cannot be set, an error will appear. You can use the canset () method to test whether it can be set. The return value of CanSet() method is False. You can use the Elem() method to make it a settable state. You need to get the pointer before using the Elem method.
var Num float64= 3.15 Value := reflect.ValueOf(Num) if ok := Value.CanSet(); ok { fmt.Println("Value Can Set") Value.SetFloat(4.56) }else{ fmt.Println("Value Cannot Set, Now Elem it") Value := reflect.ValueOf(&Num) Value = Value.Elem() fmt.Println("The CanSet Is ", Value.CanSet()) Value.SetFloat(1.23) } fmt.Println(Value)
Output results:
Value Cannot Set, Now Elem it The CanSet Is true 3.15
Be careful to reuse reflect. Before using the Elem method ValueOf(&Num)
Reflective structure
Sometimes you need to reflect a structure type. The NumField() method returns the number of fields within the structure. Get the value field (I) of each field by index through a for loop. At the same time, we can call the method on the signature structure, and we can use the index to call method (n) Call( nil ).
type ThreeString struct{ s1,s2,s3 string } func (s ThreeString)String() string{ return s.s1 + "-" + s.s2 + "-"+s.s3 } var secret interface{}=ThreeString{"Alpha","Bete","Omega"} func main(){ Value1 := reflect.ValueOf(secret) Type1 := reflect.TypeOf(secret) fmt.Println(Type1) fmt.Println(Value1.Kind()) for i := 0 ; i < Value1.NumField() ; i++ { fmt.Printf("Field %d : %v\n",i,Value1.Field(i)) } fmt.Println(Value1) results := Value1.Method(0).Call(nil) fmt.Println(results) }
Output results:
main.ThreeString struct Field 0 : Alpha Field 1 : Bete Field 2 : Omega Alpha-Bete-Omega [Alpha-Bete-Omega]
However, if field (n) is used To change a value with the setstring() method, an error occurs:
panic: reflect: reflect.Value.SetString using value obtained using unexported field
Because only the exported fields (initial capitalization) in the structure can be set:
type T struct { A int B string } func main() { 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:%s %s = %v \n", i, typeOfT.Field(i).Name , f.Type(),f.Interface()) } s.Field(0).SetInt(77) s.Field(1).SetString("Sunset Strip") fmt.Println("t is now :",t) }
Output results:
0:A int = 23 1:B string = skidoo t is now : {77 Sunset Strip}
Code download
The above program codes have been uploaded to https://github.com/MrLeea-13155bc/Golang , you can download it directly if necessary