很多文章在講解GoLang的反射機制的時候都講的比較複雜,這裏簡單總結下,作一個淺顯的入門教程:this
一、TypeOf方法跟ValueOf方法spa
TypeOf用來返回變量的類型,ValueOf用來返回變量的方法。指針
咱們在初始化一個結構體的時候,有兩種方式,var a Struct跟a :=new(Struct),其中,前者的類型是struct,後者的類型是指針。code
package main import ( "fmt" "reflect" ) type MyStruct struct { name string } func (this *MyStruct) GetName() string { return this.name } func main() { a := new(MyStruct) a.name = "yejianfeng" typ := reflect.TypeOf(a) fmt.Println(typ) fmt.Println("-------------------") var b MyStruct b.name = "abc" fmt.Println(reflect.TypeOf(b)) }
輸出以下:教程
*main.MyStructstring
-------------------入門
main.MyStructimport
二、reflect.ValueOf(a).FieldByName方法變量
若是a是結構體,reflect.ValueOf(a).FieldByName("name")等價於a.name。反射
若是是指針的話ValueOf返回的是指針的Type,它是沒有Field的,因此也就不能使用FieldByName
三、CanSet方法
CanSet當Value是可尋址的時候,返回true,不然返回false。
當前面的CanSet是一個指針的時候(p)它是不可尋址的,可是當是p.Elem()(實際上就是*p),它就是能夠尋址的
package main import ( "fmt" "reflect" ) type MyStruct struct { name string } func (this *MyStruct) GetName() string { return this.name } func main() { var a MyStruct a.name = "xiangli" fmt.Println(reflect.ValueOf(a).FieldByName("name").CanSet()) //false fmt.Println(reflect.ValueOf(&(a.name)).Elem().CanSet()) //true fmt.Println("--------------") var c string = "yejianfeng" p := reflect.ValueOf(&c) fmt.Println(p.CanSet()) //false fmt.Println(p.Elem().CanSet()) //true p.Elem().SetString("newName") fmt.Println(c) }
func main() { a := new(MyStruct) a.name = "yejianfeng" fmt.Println(reflect.TypeOf(a)) fmt.Println(reflect.ValueOf(a)) fmt.Println(reflect.ValueOf(a).Elem().Type()) fmt.Println(reflect.TypeOf(a).Elem()) fmt.Println("-------------------") var b MyStruct b.name = "abc" fmt.Println(reflect.TypeOf(b)) fmt.Println(reflect.ValueOf(b)) }
返回值爲:
*main.MyStruct
&{yejianfeng}
main.MyStruct
main.MyStruct
-------------------
main.MyStruct
{abc}