亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

揭秘Go語言中的反射機(jī)制

 更新時間:2023年10月25日 08:38:39   作者:Shasha^^  
在Go語言中,反射是通過reflect包來實(shí)現(xiàn)的,通過使用反射,我們可以在運(yùn)行時獲取對象的類型信息、訪問對象的字段和方法、動態(tài)調(diào)用方法等,反射在很多場景下都非常有用,比如編寫通用的代碼、實(shí)現(xiàn)對象的序列化和反序列化、實(shí)現(xiàn)依賴注入等,需要的朋友可以參考下

基本概念

支持反射的語言可以在程序編譯期將變量的反射信息,如字段名稱、類型信息、結(jié)構(gòu)體信息等整合到可執(zhí)行文件中,并給程序提供接口訪問反射信息,這樣就可以在程序運(yùn)行期獲取類型的反射信息,并且有能力修改它們。

Go語言提供了 reflect 包來訪問程序的反射信息。

Refelct解析

Refelct包 定義了兩個重要的類型 Type 和 Value,任意接口在反射中都可以理解為 由 reflect.Type 和 reflect.Value 兩部分組成 。簡單來說,go 的接口是由兩部分組成的,一部分是類型信息,另一部分是數(shù)據(jù)信息

eg

var a=1
var b interface{}=a

對于 這個例子,b 的類型信息是 int,數(shù)據(jù)信息是 1,這兩部分信息都是存儲在 b 里面的。b 的內(nèi)存結(jié)構(gòu)如下:

而 b實(shí)際上是一個空接口,也就是說一個 interface{} 中實(shí)際上既包含了變量的類型信息,也包含了類型的數(shù)據(jù)

refelct.Type ,refelct.Value
如上所說,所有的接口都含有type 和value ,我們可以使用refelct包中的 typeof 和valueof將信息從接口中取出

var a = 1
t := reflect.TypeOf(a)

var b = "hello"
t1 := reflect.ValueOf(b)

反射定律

三條反射定律 :

  1. 反射可以將 interface 類型變量轉(zhuǎn)換成反射對象。
  2. 反射可以將反射對象還原成 interface 對象。
  3. 如果要修改反射對象,那么反射對象必須是可設(shè)置的(CanSet)。

將 interface 類型變量轉(zhuǎn)換成反射對象

我們可以通過 reflect.TypeOf 和 reflect.ValueOf 來獲取到一個變量的反射類型和反射值。

var a = 1
typeOfA := reflect.TypeOf(a)
valueOfA := reflect.ValueOf(a)

將反射對象還原成 interface 對象。

我們可以通過 reflect.Value.Interface 來獲取到反射對象的 interface 對象,也就是傳遞給 reflect.ValueOf 的那個變量本身。 不過返回值類型是 interface{},所以我們需要進(jìn)行類型斷言。

i := valueOfA.Interface()
fmt.Println(i.(int))

修改反射對象

通過 reflect.Value.CanSet 來判斷一個反射對象是否是可設(shè)置的。如果是可設(shè)置的,我們就可以通過 reflect.Value.Set 來修改反射對象的值。

var x float64 = 3.4
v := reflect.ValueOf(&x)
fmt.Println("settability of v:", v.CanSet()) // false
fmt.Println("settability of v:", v.Elem().CanSet()) // true

那什么情況下一個反射對象是可設(shè)置的呢?前提是這個反射對象是一個指針,然后這個指針指向的是一個可設(shè)置的變量 .

在上面這個例子中,v.CanSet() 返回的是 false,而 v.Elem().CanSet() 返回的是 true。

在這里,v是一根指針,但是v.Elem()才是v這根指針指向的值。Elem方法是一個解引用的作用。對于這個指針本身,我們修改它是沒有意義的,我們可以設(shè)想一下, 如果我們修改了指針變量(也就是修改了指針變量指向的地址),那會發(fā)生什么呢?那樣我們的指針變量就不是指向 x 了, 而是指向了其他的變量,這樣就不符合我們的預(yù)期了。所以 v.CanSet() 返回的是 false。

而 v.Elem().CanSet() 返回的是 true。這是因?yàn)?v.Elem() 才是 x 本身,通過 v.Elem() 修改 x 的值是沒有問題的


Elem()

refelct.Value中的Elem

reflect.Value 的 Elem 方法的作用是獲取指針指向的值,或者獲取接口的動態(tài)值。

對于指針很好理解,其實(shí)作用類似解引用。而對于接口,還是要回到 interface 的結(jié)構(gòu)本身,因?yàn)榻涌诶锇祟愋秃蛿?shù)據(jù)本身,所以 Elem 方法就是獲取接口的數(shù)據(jù)部分(也就是 iface 或 eface 中的 data 字段)。

refelct.Type中的Elem

reflect.Type 的 Elem 方法的作用是獲取數(shù)組、chan、map、指針、切片關(guān)聯(lián)元素的類型信息,也就是說,對于 reflect.Type 來說, 能調(diào)用 Elem 方法的反射對象,必須是數(shù)組、chan、map、指針、切片中的一種,其他類型的 reflect.Type 調(diào)用 Elem 方法會 panic。

t1 := reflect.TypeOf([3]int{1, 2, 3}) // 數(shù)組 [3]int
fmt.Println(t1.String()) // [3]int
fmt.Println(t1.Elem().String()) // int

需要注意的是,如果我們要獲取 map 類型 key 的類型信息,需要使用 Key 方法,而不是 Elem 方法。

m := make(map[string]string)
t1 := reflect.TypeOf(m)
fmt.Println(t1.Key().String()) // string

反射是Go語言中一種強(qiáng)大的編程技術(shù),它允許程序在運(yùn)行時動態(tài)地檢查和修改對象的結(jié)構(gòu)和行為。通過使用reflect包,我們可以在運(yùn)行時獲取對象的類型信息、訪問對象的字段和方法、動態(tài)調(diào)用方法等。反射在很多場景下都非常有用,比如編寫通用的代碼、實(shí)現(xiàn)對象的序列化和反序列化、實(shí)現(xiàn)依賴注入等。然而,反射的使用也需要謹(jǐn)慎,因?yàn)樗鼤硪欢ǖ男阅軗p耗。在實(shí)際開發(fā)中,我們應(yīng)該根據(jù)具體的需求來判斷是否需要使用反射。總的來說,反射是Go語言中一個非常有用的特性,它為我們提供了更大的靈活性和擴(kuò)展性。

到此這篇關(guān)于揭秘Go語言中的反射機(jī)制的文章就介紹到這了,更多相關(guān)Go語言反射機(jī)制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go語言中你不知道的Interface詳解

    Go語言中你不知道的Interface詳解

    對于go語言來說,設(shè)計(jì)最精妙的應(yīng)該是interface了,直白點(diǎn)說interface是一組method的組合。下面這篇文章主要給大家介紹了關(guān)于Go語言中你不知道的Interface的相關(guān)資料,需要的朋友可以參考借鑒,下面來一起看看吧。
    2018-02-02
  • Golang中數(shù)據(jù)結(jié)構(gòu)Queue的實(shí)現(xiàn)方法詳解

    Golang中數(shù)據(jù)結(jié)構(gòu)Queue的實(shí)現(xiàn)方法詳解

    這篇文章主要給大家介紹了關(guān)于Golang中數(shù)據(jù)結(jié)構(gòu)Queue的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-09-09
  • Go語言中的函數(shù)式編程實(shí)踐

    Go語言中的函數(shù)式編程實(shí)踐

    這篇文章主要介紹了Go語言中的函數(shù)式編程實(shí)踐,主要講解Go語言中的函數(shù)式編程概念和使用。小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-05-05
  • Golang 利用反射對結(jié)構(gòu)體優(yōu)雅排序的操作方法

    Golang 利用反射對結(jié)構(gòu)體優(yōu)雅排序的操作方法

    這篇文章主要介紹了Golang 利用反射對結(jié)構(gòu)體優(yōu)雅排序的操作方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-10-10
  • goland安裝1.7版本報(bào)錯Unpacked?SDK?is?corrupted解決

    goland安裝1.7版本報(bào)錯Unpacked?SDK?is?corrupted解決

    這篇文章主要為大家介紹了goland安裝1.7版本報(bào)錯Unpacked?SDK?is?corrupted解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • Golang通脈之?dāng)?shù)據(jù)類型詳情

    Golang通脈之?dāng)?shù)據(jù)類型詳情

    這篇文章主要介紹了Golang通脈之?dāng)?shù)據(jù)類型,在編程語言中標(biāo)識符就是定義的具有某種意義的詞,比如變量名、常量名、函數(shù)名等等,Go語言中標(biāo)識符允許由字母數(shù)字和_(下劃線)組成,并且只能以字母和_開頭,更詳細(xì)內(nèi)容請看下面文章吧
    2021-10-10
  • Go?Java?算法之字符串解碼示例詳解

    Go?Java?算法之字符串解碼示例詳解

    這篇文章主要為大家介紹了Go?Java?算法之字符串解碼示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • GoFrame?gredis緩存DoVar及Conn連接對象的自動序列化

    GoFrame?gredis緩存DoVar及Conn連接對象的自動序列化

    這篇文章主要為大家介紹了GoFrame?gredis干貨DoVar?Conn連接對象自動序列化詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • golang 跳出多重循環(huán)的高級break用法說明

    golang 跳出多重循環(huán)的高級break用法說明

    這篇文章主要介紹了golang 跳出多重循環(huán)的高級break用法說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • 淺析go中Ticker,Timer和Tick的用法與區(qū)別

    淺析go中Ticker,Timer和Tick的用法與區(qū)別

    在go面試的時候,面試官經(jīng)常會問time包的Ticker,Timer以及Tick的區(qū)別,一般在超時控制的時候用的比較多,今天就跟隨小編一起來詳細(xì)學(xué)一下這幾個的區(qū)別吧
    2023-10-10

最新評論