反射(reflection)是指在運(yùn)行時(shí),動(dòng)態(tài)獲取程序結(jié)構(gòu)信息(元信息)的一種能力,是靜態(tài)類型語言都支持的一種特性,如Java, golang等。這里主要詳細(xì)介紹golang reflection相關(guān)知識(shí)
公司主營業(yè)務(wù):網(wǎng)站設(shè)計(jì)制作、成都網(wǎng)站制作、移動(dòng)網(wǎng)站開發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競爭能力。創(chuàng)新互聯(lián)是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對我們的高要求,感謝他們從不同領(lǐng)域給我們帶來的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會(huì)用頭腦與智慧不斷的給客戶帶來驚喜。創(chuàng)新互聯(lián)推出海陵免費(fèi)做網(wǎng)站回饋大家。
type MyInt int var i int var j MyInt
i 為int類型,j為MyInt類型。雖然i,j底層類型均為int,但它們屬于不同類型,沒有轉(zhuǎn)換不能相互賦值。
接口類型 interface, 表示一系列方法集合,任意concrete (non-interface) value 只要實(shí)現(xiàn)了接口方法,便可賦值給interface
// 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.Reader r = os.Stdin r = bufio.NewReader(r) r = new(bytes.Buffer) // and so on
r變量的靜態(tài)類型為io.Reader,實(shí)際類型可能是File, Buffer類型
interface{} 特殊接口類型,沒有任何方法,因此任何類型都可賦值給它
var r io.Reader r = new(bytes.Buffer)
r變量的具體類型是io.Reader,實(shí)際類型是bytes.Buffer,那么在運(yùn)行時(shí),golang是如何實(shí)現(xiàn)的呢?
一個(gè)interface類型的變量存儲(chǔ)了2個(gè)信息, 一個(gè)值,類型對<value,type> pair:
賦給變量的值(concrete value)
變量值的類型描述符(value's type descriptor)
var r io.Reader tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0) if err != nil { return nil, err } r = tty
接口類型r 的<value, type> pair是(tty
, *os.File
)
當(dāng)然r變量的value tty不僅僅實(shí)現(xiàn)了io.Reader接口中的Read方法,還實(shí)現(xiàn)了io.Writer中的Write方法,因此可以進(jìn)行
類型斷言(type assertion),試圖將r 轉(zhuǎn)換為io.Writer
var w io.Writer w = r.(io.Writer)
此時(shí),接口變量w的<value,type>pair 為 (tty
, *os.File
),也就是說r,w 底層value是一樣的,可以通過不同的type來暴露不同的方法出來。
繼續(xù)討論
var empty interface{} empty = w //此處不需要type assertion,因?yàn)槿我忸愋投伎梢钥醋鲗?shí)現(xiàn)了empty interface的方法
接口變量empty的<value,type> pair 為 (tty
, *os.File
)
反射,可以獲取interface類型變量的具體信息(<value,concrete type>)
golang 反射包為reflect
// ValueOf returns a new Value initialized to the concrete value // stored in the interface i. ValueOf(nil) returns the zero Value. func ValueOf(i interface{}) Value //獲取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 //獲取pair中的concrete type
eg:
var r io.Reader r = os.Stdin // <value, type> : <os.Stdin, *os.File> rValue := reflect.ValueOf(r) rType := reflect.TypeOf(r) fmt.Println("value:", rValue) fmt.Println("type :", rType) 輸出: value: &{0xc04205a000} //指針 type : *os.File var f float64 f = 1.234 fmt.Println("f value:",reflect.ValueOf(f)) fmt.Println("f type :",reflect.TypeOf(f)) 輸出: f value: 1.234 f type : float64
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 = user uValue := reflect.ValueOf(i) uType := reflect.TypeOf(i) fmt.Println("uValue: ",uValue) fmt.Println(uValue.Interface()) //轉(zhuǎn)換為interface類型,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++ { //獲取field信息 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++ {// 獲取method信息 method := uType.Method(i) fmt.Printf("method[%d] = %s \n",i,method.Name) } fmt.Println(uValue.Kind()) fmt.Println(uType.Kind())
var x float64 = 3.4 v := reflect.ValueOf(x) fmt.Println("settability of v:", v.CanSet()) //print: settability of v: false v.SetFloat(7.1) // Error: will panic.
不可修改的原因:we pass a copy of x
to reflect.ValueOf
, so the interface value created as the argument to reflect.ValueOf
is a copy of x
, not x
itself
解決辦法,傳遞指針!!
var x float64 = 3.4 p := 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: *float64 settability of p: false //why ? p不可set,p指向的內(nèi)容可set,p指向的內(nèi)容即*p,如何獲得p指向的內(nèi)容?
reflect.Value 的Elem方法,可以獲取value 指向的內(nèi)容
v := p.Elem() fmt.Println("settability of v:", v.CanSet())//settability of v: true v.SetFloat(7.1) fmt.Println(v.Interface()) //7.1 fmt.Println(x) //7.1
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(24) s.Field(1).SetString("Sunset Strip") fmt.Println("after change: ",s.Interface())
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(30)} 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)
文章名稱:理解golang反射(reflectioninGo)
網(wǎng)站地址:http://bm7419.com/article20/pcidco.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信公眾號(hào)、電子商務(wù)、自適應(yīng)網(wǎng)站、虛擬主機(jī)、外貿(mào)建站、品牌網(wǎng)站設(shè)計(jì)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)