Golang?reflect反射的使用實(shí)例
首先有一段以下結(jié)構(gòu)體的定義
type User struct { UserName string UserId int `name:"uid"` }
初始化一個(gè)結(jié)構(gòu)體的實(shí)例
u := User{"octoboy", 101}
獲取字段名
首先獲取變量的Type變量
t := reflect.TypeOf(u)
需要注意的是,如果傳入的u是個(gè)指針,比如&User{"octoboy", 101}
if t.Kind() == reflect.Ptr { t = t.Elem() }
這里通過(guò)Kind()函數(shù)獲取變量的類(lèi)型,判斷如果類(lèi)型為指針 需要使用Elem()獲取指針指向的內(nèi)容。
然后遍歷結(jié)構(gòu)體的字段,獲取其字段名稱(chēng)
for i := 0; i < t.NumField(); i++ { fmt.Println(t.Field(i).Name) }
輸出結(jié)果:
UserName
UserId
獲取字段類(lèi)型和值
v := reflect.ValueOf(u) if v.Kind() == reflect.Ptr { //類(lèi)型為指針 需要取elem v = v.Elem() }
獲取字段的值或者賦值,需要用到ValueOf方法
for i := 0; i < v.NumField(); i++ { //v.Field(i).Int() v.Field(i).String() 都可以把值返回出來(lái),相當(dāng)于斷言 類(lèi)型不匹配會(huì)直接panic //直接斷成interface 任意類(lèi)型 fmt.Println(v.Field(i).Interface()) }
輸出結(jié)果:
zyg
101
繼續(xù)輸出成員變量的類(lèi)型
for i := 0; i < v.NumField(); i++ { fmt.Println(v.Field(i).Kind()) }
輸出結(jié)果:
string
int
設(shè)置字段值
靜態(tài)賦值
//設(shè)置字段值 va := reflect.ValueOf(&u) //這里必須使用指針 否則后面調(diào)用Set無(wú)法使用無(wú)地址的值 if va.Kind() == reflect.Ptr { //類(lèi)型為指針 需要取elem 意為取它指向的內(nèi)容值 va = va.Elem() for i := 0; i < va.NumField(); i++ { //兩種方法取設(shè)置字段的值,第二種更為統(tǒng)一 if va.Field(i).Kind() == reflect.String { //重要 如果需要使用set取修改u中的值,需要在ValueOf中傳入u的地址。否則會(huì)因?yàn)镾etString使用了一個(gè)不能被尋址的值而造成panic va.Field(i).SetString("octoboy") } if va.Field(i).Kind() == reflect.Int { va.Field(i).Set(reflect.ValueOf(123)) } }
interface切片映射成結(jié)構(gòu)體(動(dòng)態(tài)賦值)
//練手 values := []interface{}{"octoboy", 123} for i := 0; i < va.NumField(); i++ { if reflect.ValueOf(values[i]).Kind() == va.Field(i).Kind() { va.Field(i).Set(reflect.ValueOf(values[i])) } }
打印以上兩種結(jié)構(gòu)題變量
輸出結(jié)果:
&{octoboy 123}
進(jìn)階—map映射成結(jié)構(gòu)體
有如下代碼
//練習(xí) 把map映射成struct set := map[string]interface{}{ "UserName": "zyg", "UserId": 101, "Age": 19, "Sex": 1, } user := &User{} MapToStruct(set, user) fmt.Println(user)
要求將map映射到user結(jié)構(gòu)題中,即如果User的字段名如存在于map的key中,則將對(duì)應(yīng)的value值賦給user結(jié)構(gòu)題的成員變量
有如下實(shí)現(xiàn)
//str類(lèi)型為interface{} 代表可以傳入任意的結(jié)構(gòu)體 func MapToStruct(m map[string]interface{}, str interface{}) { val := reflect.ValueOf(str) if val.Kind() != reflect.Ptr {//必須是指針 否則無(wú)法用Set賦值 panic(any("must be ptr!")) } val = val.Elem() if val.Kind() != reflect.Struct { //指針指向的必須是結(jié)構(gòu)體 panic(any("must be struct")) } for i := 0; i < val.NumField(); i++ { name := val.Type().Field(i).Name //value轉(zhuǎn)type后取字段名稱(chēng) if v, ok := m[name]; ok { //如果根據(jù)tag做映射,就使用val.Type().Field(i).Tag.Get("name")作為key if reflect.ValueOf(v).Kind() == val.Field(i).Kind() { val.Field(i).Set(reflect.ValueOf(v)) } } } }
總結(jié)
1.TypeOf 用Name 獲取字段名,也可以用Kind獲取字段的類(lèi)型;ValueOf 只能用Kind獲取字段的類(lèi)型。
2.使用reflect.ValueOf(u).Type()轉(zhuǎn)成type,可以與reflect.TypeOf(u)達(dá)到一樣的效果
3.如果要使用Set,SetString等方法為其賦值,reflect.ValueOf(u)這里的u必須傳入一個(gè)指針,否則無(wú)法尋址,會(huì)出現(xiàn)panic
4.reflect.ValueOf(u).Interface()可以獲取值,在實(shí)際使用過(guò)程中往往會(huì)將返回結(jié)果斷言成一個(gè)接口類(lèi)型去調(diào)用接口函數(shù)
到此這篇關(guān)于golang reflect反射的使用實(shí)例的文章就介紹到這了,更多相關(guān)go reflect反射內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go語(yǔ)言開(kāi)發(fā)中有了net/http為什么還要有g(shù)in的原理及使用場(chǎng)景解析
這篇文章主要為大家介紹了Go語(yǔ)言有了net/http標(biāo)準(zhǔn)庫(kù)為什么還要有g(shù)in第三方庫(kù)的原理及使用場(chǎng)景詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08golang 生成對(duì)應(yīng)的數(shù)據(jù)表struct定義操作
這篇文章主要介紹了golang 生成對(duì)應(yīng)的數(shù)據(jù)表struct定義操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-04-04Golang實(shí)現(xiàn)簡(jiǎn)易的rpc調(diào)用
RPC指(Remote Procedure Call Protocol)遠(yuǎn)程過(guò)程調(diào)用協(xié)議。本文將實(shí)現(xiàn)利用Golang進(jìn)行rpc調(diào)用(只實(shí)現(xiàn)一個(gè)rpc框架基本的功能,不對(duì)性能做保證),需要的可以參考一下2023-03-03詳解Go中Map類(lèi)型和Slice類(lèi)型的傳遞
這篇文章主要為大家詳細(xì)介紹了Go中Map類(lèi)型和Slice類(lèi)型的傳遞,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-11-11Golang RSA生成密鑰、加密、解密、簽名與驗(yàn)簽的實(shí)現(xiàn)
RSA 是最常用的非對(duì)稱(chēng)加密算法,本文主要介紹了Golang RSA生成密鑰、加密、解密、簽名與驗(yàn)簽的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2023-11-11基于Golang設(shè)計(jì)一套可控的定時(shí)任務(wù)系統(tǒng)
這篇文章主要為大家學(xué)習(xí)介紹了如何基于Golang設(shè)計(jì)一套可控的定時(shí)任務(wù)系統(tǒng),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-07-07Go語(yǔ)言for range(按照鍵值循環(huán))遍歷操作
這篇文章主要介紹了Go語(yǔ)言for range(按照鍵值循環(huán))遍歷操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12