1. 一篇文章教會你Go語言基礎(chǔ)之反射

        共 3311字,需瀏覽 7分鐘

         ·

        2020-12-20 16:22

        點(diǎn)擊上方“Go語言進(jìn)階學(xué)習(xí)”,進(jìn)行關(guān)注

        回復(fù)“Go語言”即可獲贈從入門到進(jìn)階共10本電子書

        四月南風(fēng)大麥黃,棗花未落桐葉長。

        前言

        Hey,大家好呀,我是碼農(nóng),星期八!,我們以前學(xué)的呀,都屬于正向定義變量,正向開發(fā)!

        但是有沒有什么辦法能反著來呢?根據(jù)變量獲取類型等操作。

        一起來看看Go的反射吧?。?!


        什么是反射

        反射,嗯...,就是反著的意思唄,就是把東西反過來。

        比如這樣的一個(gè)很簡單的代碼。

        var a int = 3fmt.Println(a)

        我們當(dāng)然知道a變量是int類型,但是反過來想,程序是怎么知道aint類型呢???

        這時(shí)候,就需要用到反射了。

        示例代碼

        v := reflect.TypeOf(a)fmt.Println(v)

        兩次代碼綜合一塊執(zhí)行結(jié)果

        第二次的第2行代碼,成功的將變量a還原出了int類型。

        什么???你為我有什么用???,嗯。。。實(shí)話實(shí)說,用的不是太多,但是必須要會的。


        反射(reflect包)

        在Go中,任何變量,都有具體類型具體值,就像var a int = 3,具體類型就是int,具體值就是3

        所以,變量的具體類型歸屬在reflect.Type,變量的具體值歸屬在reflect.Value。

        并且Go的提供了

        • reflect.TypeOf獲取具體類型。

        • reflect.ValueOf獲取具體值。

        TypeOf

        TypeOf方法可以獲取變量的具體類型

        有一個(gè)這樣的需求,定義一個(gè)函數(shù),可以接收任意類型數(shù)據(jù),通過反射打印變量類型。

        示例代碼

        函數(shù)

        func reflectType(x interface{}) {    v := reflect.TypeOf(x)    fmt.Printf("你傳入的變量類型是:%v\n",v)}

        main

        func main() {    var a int = 666    var b float64 = 3.14    var c string = "hello world"    var d [3]int = [3]int{1,26}    var e []int = []int{1,26,88}    var f map[string]interface{} = map[string]interface{}{        "Name":"張三",        "Age":18}    reflectType(a)    reflectType(b)    reflectType(c)    reflectType(d)    reflectType(e)    reflectType(f)}

        執(zhí)行結(jié)果

        通過reflect.TypeOf方法,完美解決上述需求。

        TypeOf 的Name和Kind

        這個(gè)是啥意思呢??這個(gè)在結(jié)構(gòu)體中比較好體現(xiàn)。

        簡答來說就是TypeOf返回的太籠統(tǒng)了,還有更加細(xì)化的類型,通過這倆屬性獲取。

        示例代碼

        函數(shù)
        func reflectType(x interface{}) {v := reflect.TypeOf(x)fmt.Printf("你傳入的變量類型是:%v | Name:%v | Kind:%v\n", v, v.Name(), v.Kind())}
        結(jié)構(gòu)體
        type Student struct {    Name string    Age int}
        main
        func main() {    var a int    var b *int    var c []int    var d map[string]interface{}    var e Student    reflectType(a)    reflectType(b)    reflectType(c)    reflectType(d)    reflectType(e)}

        執(zhí)行結(jié)果

        總結(jié)

        經(jīng)過對比,會發(fā)現(xiàn)幾個(gè)特殊問題。

        如果變量是指針類型,Name為空,Kindptr。

        如果變量是引用類型(切片和map)類型,Name為空,只有Kind。

        如果變量是結(jié)構(gòu)體,Name是結(jié)構(gòu)體名,Kindstruct。

        ValueOf

        TypeOf只能反過來獲取變量的具體類型,但是并不能獲取具體值,這就有點(diǎn)不太厚道了。

        所以ValueOf就來解決這個(gè)問題了,但是ValueOf牛叉的是,它里面還包括了變量類型

        注:ValueOfTypeOfKind屬性返回內(nèi)容是一摸一樣的。

        需求:定義一個(gè)函數(shù),可以接收任意類型,通過反射得出變量類型和變量值。

        函數(shù)

        func reflectType(x interface{}) {    v := reflect.ValueOf(x)    k := v.Kind()    switch k {    case reflect.Int:        fmt.Printf("我是Int類型,我的值是%v\n",v.Int())    case reflect.Slice:        fmt.Printf("我是切片類型,我的值是%v\n",v.Slice(1,2))    case reflect.Map:        fmt.Printf("我是切片類型,我的值是%v\n",v.MapKeys())    //case :可以繼續(xù)case下去  }}

        main

        func main() {  var a int = 1  var c []int = []int{1, 57, 19}  var d map[string]interface{} = map[string]interface{}{    "Name": "你好"    "Age":  18,  }  var e Student  reflectType(a)
        reflectType(c) reflectType(d) reflectType(e)}

        執(zhí)行結(jié)果

        通過反射設(shè)置值

        反射還有一個(gè)用途,就是動態(tài)的修改變量值,可能你暫時(shí)體會不到,但是語法還是要學(xué)的。

        通過反射設(shè)置值,需要用到Elem方法,并且傳入的必須是指針。

        示例代碼

        函數(shù)

        func reflectSetValue(x interface{}) {  v := reflect.ValueOf(x)  //kind也必須是Elem調(diào)用  var k = v.Elem().Kind()  switch k {  case reflect.Int:    //反射修改必須通過Elem    v.Elem().SetInt(200)  }}

        main

        func main() {  var a int = 10  fmt.Printf("a的值:%v\n", a)  //反射修改值傳入的必須是地址  reflectSetValue(&a)  fmt.Printf("a的值:%v\n", a)}

        執(zhí)行結(jié)果

        總結(jié)

        上述我們學(xué)習(xí)了Go基礎(chǔ)反射的TypeOf,TypeOf的Name和Kind,ValueOf,通過反射設(shè)置值。

        其中KindTypeValueOf中都有,通常情況下TypeOfValueOf一起使用效果更佳!

        反射這一塊,可能不是那么好理解,一定要多多下功夫!堅(jiān)持!!

        如果在操作過程中有任何問題,記得下面留言,我們看到會第一時(shí)間解決問題。我是碼農(nóng)星期八,如果覺得還不錯,記得動手點(diǎn)贊一下哈。感謝你的觀看。

        -------------------?End?-------------------

        往期精彩文章推薦:

        歡迎大家點(diǎn)贊,留言,轉(zhuǎn)發(fā),轉(zhuǎn)載,感謝大家的相伴與支持

        想加入Go學(xué)習(xí)群請?jiān)诤笈_回復(fù)【入群

        萬水千山總是情,點(diǎn)個(gè)【在看】行不行

        瀏覽 52
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評論
        圖片
        表情
        推薦
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
          
          

            1. 久久精品苍井空免费一区二 | 少妇被两个黑人3p喷水视频 | 男女操逼毛片 | 91看片国产 | 影音先锋东京热 |