Go語言基礎(chǔ)——反射

Go語言提供了一種機(jī)制朋腋,在編譯時(shí)不知道類型的情況下,在運(yùn)行時(shí)膜楷,可更新變量旭咽、查看值、調(diào)用方法以及直接對(duì)它的結(jié)構(gòu)成員進(jìn)行操作赌厅,這種機(jī)制稱為反射(reflection)穷绵。

1、Go的反射程序包:reflect

反射功能由reflect包提供特愿,包內(nèi)定義了兩個(gè)重要的類型:Type和Value仲墨。
Type表示Go語 言的一個(gè)類型,它是一個(gè)有很多方法的接口揍障,這些方法可以用來識(shí)別類型以及透視類型的組 成部分目养,比如一個(gè)結(jié)構(gòu)的各個(gè)字段或者一個(gè)函數(shù)的各個(gè)參數(shù)。reflect.Type接口只有一個(gè)實(shí)現(xiàn)毒嫡,即類型描述符癌蚁,接口值中的動(dòng)態(tài)類型也是類型描述符。
reflect.Value可以包含一任意類型的值。

通過示例展示Type和Value的使用

package main 

import (
    "fmt"
    "reflect"   //引入反射包
)

// 定義用戶結(jié)構(gòu)
type User struct {
    Id int
    Name string
    Age int
}

// 定義方法
func (u User)Hello(){
    fmt.Println("Hello World!")
}

func main() {
    u := User{1,"Tom",12}
//  Info(&u) 傳入指針類型努释,編譯報(bào)錯(cuò):panic: reflect: NumField of non-struct type
    Info(u) // 通過值拷貝輸入對(duì)象
}

// 反射示例函數(shù)
func Info(o interface{}) {
    t := reflect.TypeOf(o)  // 獲取類型數(shù)據(jù)
    fmt.Println("Type:", t.Name()) // 打印類型名稱
    
    v := reflect.ValueOf(o) // 獲取對(duì)象的數(shù)值
    fmt.Println("Fields:")
    
    for i :=0; i < t.NumField(); i++ {
        f := t.Field(i) // 獲取指定索引結(jié)構(gòu)成員的信息
        val := v.Field(i).Interface()   // 獲取指定結(jié)構(gòu)成員的值
        fmt.Printf("%6s: %v = %v\n", f.Name, f.Type, val) // 打印成員的名稱碘梢,類型和值
    }
    
    for i :=0; i <t.NumMethod(); i++ {
        m := t.Method(i) // 獲取指定索引的方法的信息
        fmt.Printf("%6s: %v\n", m.Name, m.Type) // 打印方法的名稱,方法聲明
    }
}

程序運(yùn)行輸出的結(jié)果如下圖:


圖片.png

2伐蒂、匿名字段的反射

在Go語言中煞躬,可以通過索引來獲取匿名字段的信息,參見程序代碼:

package main 

import (
    "fmt"
    "reflect"   //引入反射包
)

// 定義用戶結(jié)構(gòu)
type User struct {
    Id int
    Name string
    Age int
}

type Manager struct {
    User    // 定義匿名字段
    title string
}

func main() {
    m := Manager{User: User{1, "Lisa", 28}, title: "CFO"}   // 對(duì)象定義及匿名User類型字段初始化
    t := reflect.TypeOf(m)  // 獲取對(duì)象的類型信息
    
    fmt.Printf("%#v\n", t.Field(0)) // 通過索引獲取匿名字段的信息
    fmt.Printf("%#v\n", t.Field(1)) // 獲取title字段的信息
    
    // 獲取匿名User類型字段成員的方法逸邦,通過傳入slice來制定索引對(duì)應(yīng)的成員恩沛,可以獲取相應(yīng)的信息
    fmt.Printf("%#v\n", t.FieldByIndex([]int{0,0})) //獲取User中的Id成員
    fmt.Printf("%#v\n", t.FieldByIndex([]int{0,1})) //獲取User中的Name成員
}

運(yùn)行輸出結(jié)果:


圖片.png

上圖中,可以看到昭雌,對(duì)于User類型的匿名成員的名稱為:User复唤,是否匿名Anonymous標(biāo)記為:true,而對(duì)于User成員Id和Name來講烛卧,匿名標(biāo)記為false佛纫。

3、通過反射修改結(jié)構(gòu)對(duì)象的值

package main 

import (
    "fmt"
    "reflect"   //引入反射包
)

// 定義用戶結(jié)構(gòu)
type User struct {
    Id int
    Name string
    Age int
}

func main() {
    u := User{1,"Tom", 28}
    fmt.Println("before:",u)
    Set(&u)
    fmt.Println("after:",u)
}

func Set(o interface{}) {
    v := reflect.ValueOf(o)
    
    if v.Kind() == reflect.Ptr && !v.Elem().CanSet() {
        fmt.Print("輸入的對(duì)象是不可修改的")
    } else {
        v = v.Elem()
    }
     // 判斷是否獲取到制定名稱的字段信息
    f := v.FieldByName("Name")
    if !f.IsValid() {
        fmt.Println("沒有找到Name的字段")
        return
    }
    // 修改字段的數(shù)值
    if f.Kind() == reflect.String {
        f.SetString("Tom2")
    } 
    
}

運(yùn)行結(jié)果如下:

圖片.png

reflect 包中還有很多有用的方法总放,具體詳見包的參考文檔及源碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末呈宇,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子局雄,更是在濱河造成了極大的恐慌甥啄,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,348評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件炬搭,死亡現(xiàn)場(chǎng)離奇詭異蜈漓,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)宫盔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門融虽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人灼芭,你說我怎么就攤上這事有额。” “怎么了彼绷?”我有些...
    開封第一講書人閱讀 156,936評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵巍佑,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我寄悯,道長(zhǎng)萤衰,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,427評(píng)論 1 283
  • 正文 為了忘掉前任猜旬,我火速辦了婚禮脆栋,結(jié)果婚禮上胳螟,老公的妹妹穿的比我還像新娘。我一直安慰自己筹吐,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,467評(píng)論 6 385
  • 文/花漫 我一把揭開白布秘遏。 她就那樣靜靜地躺著丘薛,像睡著了一般。 火紅的嫁衣襯著肌膚如雪邦危。 梳的紋絲不亂的頭發(fā)上洋侨,一...
    開封第一講書人閱讀 49,785評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音倦蚪,去河邊找鬼希坚。 笑死,一個(gè)胖子當(dāng)著我的面吹牛陵且,可吹牛的內(nèi)容都是我干的裁僧。 我是一名探鬼主播,決...
    沈念sama閱讀 38,931評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼慕购,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼聊疲!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起沪悲,我...
    開封第一講書人閱讀 37,696評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤获洲,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后殿如,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體贡珊,經(jīng)...
    沈念sama閱讀 44,141評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,483評(píng)論 2 327
  • 正文 我和宋清朗相戀三年涉馁,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了门岔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,625評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡谨胞,死狀恐怖固歪,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情胯努,我是刑警寧澤牢裳,帶...
    沈念sama閱讀 34,291評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站叶沛,受9級(jí)特大地震影響蒲讯,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜灰署,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,892評(píng)論 3 312
  • 文/蒙蒙 一判帮、第九天 我趴在偏房一處隱蔽的房頂上張望局嘁。 院中可真熱鬧,春花似錦晦墙、人聲如沸悦昵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至纸型,卻和暖如春背镇,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人剩岳。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像入热,于是被迫代替她去往敵國(guó)和親拍棕。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,492評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理才顿,服務(wù)發(fā)現(xiàn)莫湘,斷路器,智...
    卡卡羅2017閱讀 134,629評(píng)論 18 139
  • 第一次知道反射的時(shí)候還是許多年前在學(xué)校里玩 C# 的時(shí)候郑气。那時(shí)總是弄不清楚這個(gè)復(fù)雜的玩意能有什么實(shí)際用途……然后發(fā)...
    勿以浮沙筑高臺(tái)閱讀 1,125評(píng)論 0 9
  • 首先巴拉巴拉一下golang反射機(jī)制的三個(gè)定律 1.反射可以從接口類型到反射類型對(duì)象 2.反射可以從反射類型對(duì)象到...
    吃貓的魚0閱讀 2,898評(píng)論 0 1
  • 只要你下定決心尾组,就過你想要的生活忙芒,不管有錢還是沒錢。你可以繼續(xù)看你的書讳侨,保持你的想法呵萨,只用對(duì)自己說“我是自由人】缈纾”...
    無邪說在簡(jiǎn)書閱讀 282評(píng)論 0 1
  • 一潮峦、本期目標(biāo): 建立和諧的家庭關(guān)系,改善緩和父子關(guān)系勇婴。 愿景:擁有一個(gè)幸福和諧的家庭忱嘹,一家人友好相處相互信...
    夏寧點(diǎn)點(diǎn)閱讀 113評(píng)論 0 0