真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Go語(yǔ)言之反射

和Java語(yǔ)言一樣,Go也實(shí)現(xiàn)運(yùn)行時(shí)反射,這為我們提供一種可以在運(yùn)行時(shí)操作任意類型對(duì)象的能力。比如我們可以查看一個(gè)接口變量的具體類型,看看一個(gè)結(jié)構(gòu)體有多少字段,如何修改某個(gè)字段的值等。

讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛(ài)。我們立志把好的技術(shù)通過(guò)有效、簡(jiǎn)單的方式提供給客戶,將通過(guò)不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:國(guó)際域名空間、虛擬空間、營(yíng)銷軟件、網(wǎng)站建設(shè)、相城網(wǎng)站維護(hù)、網(wǎng)站推廣。


TypeOf和ValueOf


在Go的反射定義中,任何接口都會(huì)由兩部分組成的,一個(gè)是接口的具體類型,一個(gè)是具體類型對(duì)應(yīng)的值。比如var i int = 3 ,因?yàn)閕nterface{}可以表示任何類型,所以變量i可以轉(zhuǎn)為interface{},所以可以把變量i當(dāng)成一個(gè)接口,那么這個(gè)變量在Go反射中的表示就是,其中Value為變量的值3,Type變量的為類型int。


在Go反射中,標(biāo)準(zhǔn)庫(kù)為我們提供兩種類型來(lái)分別表示他們r(jià)eflect.Value和reflect.Type,并且提供了兩個(gè)函數(shù)來(lái)獲取任意對(duì)象的Value和Type。


func main(){    u:=User{"張三",20}    t:=reflect.TypeOf(u)    fmt.Println(t)
}
typeUserstruct{    Namestring    Ageint
}

reflect.TypeOf可以獲取任意對(duì)象的具體類型,這里通過(guò)打印輸出可以看到是main.User這個(gè)結(jié)構(gòu)體型。reflect.TypeOf函數(shù)接受一個(gè)空接口interface{}作為參數(shù),所以這個(gè)方法可以接受任何類型的對(duì)象。


接著上面的例子,我們看下如何反射獲取一個(gè)對(duì)象的Value。


 v:=reflect.ValueOf(u)
    fmt.Println(v)

和TypeOf函數(shù)一樣,也可以接受任意對(duì)象,可以看到打印輸出為{張三 20}。對(duì)于以上這兩種輸出,Go語(yǔ)言還通過(guò)fmt.Printf函數(shù)為我們提供了簡(jiǎn)便的方法。


    fmt.Printf("%T\n",u)
    fmt.Printf("%v\n",u)

這個(gè)例子和以上的例子中的輸出一樣。


reflect.Value轉(zhuǎn)原始類型


上面的例子我們可以通過(guò)reflect.ValueOf函數(shù)把任意類型的對(duì)象轉(zhuǎn)為一個(gè)reflect.Value,那我們?nèi)绻覀兿肽嫦蜣D(zhuǎn)過(guò)回來(lái)呢,其實(shí)也是可以的,reflect.Value為我們提供了Inteface方法來(lái)幫我們做這個(gè)事情。繼續(xù)接上面的例子:


    u1:=v.Interface().(User)
    fmt.Println(u1)

這樣我們就又還原為原來(lái)的User對(duì)象了,通過(guò)打印的輸出就可以驗(yàn)證。這里可以還原的原因是因?yàn)樵贕o的反射中,把任意一個(gè)對(duì)象分為reflect.Value和reflect.Type,而reflect.Value又同時(shí)持有一個(gè)對(duì)象的reflect.Value和reflect.Type,所以我們可以通過(guò)reflect.Value的Interface方法實(shí)現(xiàn)還原?,F(xiàn)在我們看看如何從一個(gè)reflect.Value獲取對(duì)應(yīng)的reflect.Type。


  t1:=v.Type()
    fmt.Println(t1)

如上例中,通過(guò)reflect.Value的Type方法就可以獲得對(duì)應(yīng)的reflect.Type。


獲取類型底層類型


底層的類型是什么意思呢?其實(shí)對(duì)應(yīng)的主要是基礎(chǔ)類型,接口、結(jié)構(gòu)體、指針這些,因?yàn)槲覀兛梢酝ㄟ^(guò)type關(guān)鍵字聲明很多新的類型,比如上面的例子,對(duì)象u的實(shí)際類型是User,但是對(duì)應(yīng)的底層類型是struct這個(gè)結(jié)構(gòu)體類型,我們來(lái)驗(yàn)證下。


fmt.Println(t.Kind())

通過(guò)Kind方法即可獲取,非常簡(jiǎn)單,當(dāng)然我們也可以使用Value對(duì)象的Kind方法,他們是等價(jià)的。

Go語(yǔ)言提供了以下這些最底層的類型,可以看到,都是最基本的。


const(    InvalidKind= iota    
   Bool    Int    Int8    Int16    Int32    Int64    Uint    Uint8    Uint16    Uint32    Uint64    Uintptr    Float32    Float64    Complex64    Complex128    Array    Chan    Func    Interface    Map    Ptr    Slice    String    Struct    UnsafePointer
)

遍歷字段和方法


通過(guò)反射,我們可以獲取一個(gè)結(jié)構(gòu)體類型的字段,也可以獲取一個(gè)類型的導(dǎo)出方法,這樣我們就可以在運(yùn)行時(shí)了解一個(gè)類型的結(jié)構(gòu),這是一個(gè)非常強(qiáng)大的功能。


for i:=0;i


這個(gè)例子打印出結(jié)構(gòu)體的所有字段名以及該結(jié)構(gòu)體的方法。NumField方法獲取結(jié)構(gòu)體有多少個(gè)字段,然后通過(guò)Field方法傳遞索引的方式,循環(huán)獲取每一個(gè)字段,然后打印出他們的名字。


同樣的對(duì)于方法也類似,這里不再贅述。


修改字段的值


假如我們想在運(yùn)行中動(dòng)態(tài)的修改某個(gè)字段的值有什么辦法呢?一種就是我們常規(guī)的有提供的方法或者導(dǎo)出的字段可以供我們修改,還有一種是使用反射,這里主要介紹反射。


func main(){    x:=2    v:=reflect.ValueOf(&x)    v.Elem().SetInt(100)    fmt.Println(x)
}

以上就是通過(guò)反射修改一個(gè)變量的例子。


因?yàn)閞eflect.ValueOf函數(shù)返回的是一份值的拷貝,所以前提是我們是傳入要修改變量的地址。


其次需要我們調(diào)用Elem方法找到這個(gè)指針指向的值。


最后我們就可以使用SetInt方法修改值了。


以上有幾個(gè)重點(diǎn),才可以保證值可以被修改,Value為我們提供了CanSet方法可以幫助我們判斷是否可以修改該對(duì)象。


我們現(xiàn)在可以更新變量的值了,那么如何修改結(jié)構(gòu)體字段的值呢?大家自己試試。


動(dòng)態(tài)調(diào)用方法

結(jié)構(gòu)體的方法我們不光可以正常的調(diào)用,還可以使用反射進(jìn)行調(diào)用。要想反射調(diào)用,我們先要獲取到需要調(diào)用的方法,然后進(jìn)行傳參調(diào)用,如下示例:


func main(){    u:=User{"張三",20}    v:=reflect.ValueOf(u)
    mPrint:=v.MethodByName("Print")    args:=[]reflect.Value{reflect.ValueOf("前綴")}    fmt.Println(mPrint.Call(args))
}
typeUserstruct{    Namestring    Ageint
}
func(uUser)Print(prfixstring){    fmt.Printf("%s:Name is %s,Age is %d",prfix,u.Name,u.Age)
}

MethodByName方法可以讓我們根據(jù)一個(gè)方法名獲取一個(gè)方法對(duì)象,然后我們構(gòu)建好該方法需要的參數(shù),最后調(diào)用Call就達(dá)到了動(dòng)態(tài)調(diào)用方法的目的。


獲取到的方法我們可以使用IsValid 來(lái)判斷是否可用(存在)。


這里的參數(shù)是一個(gè)Value類型的數(shù)組,所以需要的參數(shù),我們必須要通過(guò)ValueOf函數(shù)進(jìn)行轉(zhuǎn)換。


網(wǎng)站欄目:Go語(yǔ)言之反射
文章網(wǎng)址:http://weahome.cn/article/pissis.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部