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()
}這里通過Kind()函數(shù)獲取變量的類型,判斷如果類型為指針 需要使用Elem()獲取指針指向的內(nèi)容。
然后遍歷結(jié)構(gòu)體的字段,獲取其字段名稱
for i := 0; i < t.NumField(); i++ {
fmt.Println(t.Field(i).Name)
}輸出結(jié)果:
UserName
UserId
獲取字段類型和值
v := reflect.ValueOf(u)
if v.Kind() == reflect.Ptr { //類型為指針 需要取elem
v = v.Elem()
}獲取字段的值或者賦值,需要用到ValueOf方法
for i := 0; i < v.NumField(); i++ {
//v.Field(i).Int() v.Field(i).String() 都可以把值返回出來,相當(dāng)于斷言 類型不匹配會(huì)直接panic
//直接斷成interface 任意類型
fmt.Println(v.Field(i).Interface())
}輸出結(jié)果:
zyg
101
繼續(xù)輸出成員變量的類型
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無法使用無地址的值
if va.Kind() == reflect.Ptr { //類型為指針 需要取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類型為interface{} 代表可以傳入任意的結(jié)構(gòu)體
func MapToStruct(m map[string]interface{}, str interface{}) {
val := reflect.ValueOf(str)
if val.Kind() != reflect.Ptr {//必須是指針 否則無法用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后取字段名稱
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獲取字段的類型;ValueOf 只能用Kind獲取字段的類型。
2.使用reflect.ValueOf(u).Type()轉(zhuǎn)成type,可以與reflect.TypeOf(u)達(dá)到一樣的效果
3.如果要使用Set,SetString等方法為其賦值,reflect.ValueOf(u)這里的u必須傳入一個(gè)指針,否則無法尋址,會(huì)出現(xiàn)panic
4.reflect.ValueOf(u).Interface()可以獲取值,在實(shí)際使用過程中往往會(huì)將返回結(jié)果斷言成一個(gè)接口類型去調(diào)用接口函數(shù)
到此這篇關(guān)于golang reflect反射的使用實(shí)例的文章就介紹到這了,更多相關(guān)go reflect反射內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解如何使用go-acme/lego實(shí)現(xiàn)自動(dòng)簽發(fā)證書
這篇文章主要為大家詳細(xì)介紹了如何使用?go-acme/lego?的客戶端或庫完成證書的自動(dòng)簽發(fā),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-03-03
深入解析Go語言編程中slice切片結(jié)構(gòu)
這篇文章主要介紹了Go語言編程中slice切片結(jié)構(gòu),其中Append方法的用法介紹較為詳細(xì),需要的朋友可以參考下2015-10-10
golang 并發(fā)安全Map以及分段鎖的實(shí)現(xiàn)方法
這篇文章主要介紹了golang 并發(fā)安全Map以及分段鎖的實(shí)現(xiàn)方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-03-03
Go底層之http標(biāo)準(zhǔn)庫服務(wù)端實(shí)現(xiàn)原理分析
這篇文章主要介紹了Go底層之http標(biāo)準(zhǔn)庫服務(wù)端實(shí)現(xiàn)原理,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-06-06
利用Go語言實(shí)現(xiàn)流量回放工具的示例代碼
今天給大家推薦一款使用Go語言編寫的流量回放工具?--?goreplay;工作中你一定遇到過需要在服務(wù)器上抓包的場(chǎng)景,有了這個(gè)工具就可以助你一臂之力,廢話不多,我們接下來來看一看這個(gè)工具2022-09-09
go?sync.Once實(shí)現(xiàn)高效單例模式詳解
這篇文章主要為大家介紹了go?sync.Once實(shí)現(xiàn)高效單例模式詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
goland把go項(xiàng)目打包進(jìn)docker鏡像的全過程記錄
golang編譯的應(yīng)用是不需要依賴其他運(yùn)行環(huán)境的,下面這篇文章主要給大家介紹了關(guān)于goland把go項(xiàng)目打包進(jìn)docker鏡像的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2022-08-08
go語言題解LeetCode1128等價(jià)多米諾骨牌對(duì)的數(shù)量
這篇文章主要為大家介紹了go語言題解LeetCode1128等價(jià)多米諾骨牌對(duì)的數(shù)量示例詳解,2022-12-12

