最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go反射底層原理及數(shù)據(jù)結(jié)構(gòu)解析

 更新時(shí)間:2022年06月08日 10:00:35   作者:??樹獺叔叔????  
這篇文章主要介紹了Go反射底層原理及數(shù)據(jù)結(jié)構(gòu)解析,反射的實(shí)現(xiàn)和interface的組成很相似,都是由“類型”和“數(shù)據(jù)值”構(gòu)成,下面小編分享更多相關(guān)內(nèi)容需要的小伙伴可以參考一下

1. 反射的引入與介紹

在計(jì)算機(jī)科學(xué)中,反射是指計(jì)算機(jī)程序在運(yùn)行時(shí)(Run time)可以訪問、檢測和修改它本身狀態(tài)或行為的一種能力。用比喻來說,反射就是程序在運(yùn)行的時(shí)候能夠“觀察”并且修改自己的行為。

需要反射的 2 個(gè)常見場景:

  • 有時(shí)你需要編寫一個(gè)函數(shù),但是并不知道傳給你的參數(shù)類型是什么,可能是沒約定好;也可能是傳入的類型很多,這些類型并不能統(tǒng)一表示。這時(shí)反射就會用的上了。
  • 有時(shí)候需要根據(jù)某些條件決定調(diào)用哪個(gè)函數(shù),比如根據(jù)用戶的輸入來決定。這時(shí)就需要對函數(shù)和函數(shù)的參數(shù)進(jìn)行反射,在運(yùn)行期間動態(tài)地執(zhí)行函數(shù)。

Java中動態(tài)代理與AOP的實(shí)現(xiàn),就要借助這種操作。而對于我們Go語言來說,也提供了反射的機(jī)制。

有了前面對于interface{}底層數(shù)據(jù)結(jié)構(gòu)的了解,Go中的每個(gè)實(shí)例對象可以分為兩快,類型信息與數(shù)值信息。而我們Go中提供的反射機(jī)制,能分別拿到這兩塊信息。

image.png

數(shù)據(jù)interface中保存有結(jié)構(gòu)數(shù)據(jù),拿到該數(shù)據(jù)對應(yīng)的內(nèi)存地址,然后把該數(shù)據(jù)轉(zhuǎn)成interface,通過查看interface中的類型結(jié)構(gòu),就可以知道該數(shù)據(jù)的結(jié)構(gòu)了,其實(shí)以上就是Go反射通俗的原理。

image.png

2. 反射的數(shù)據(jù)結(jié)構(gòu)

type Type interface {
    // 所有的類型都可以調(diào)用下面這些函數(shù)
	// 此類型的變量對齊后所占用的字節(jié)數(shù)
	Align() int
	// 如果是 struct 的字段,對齊后占用的字節(jié)數(shù)
	FieldAlign() int
	// 返回類型方法集里的第 `i` (傳入的參數(shù))個(gè)方法
	Method(int) Method
	// 通過名稱獲取方法
	MethodByName(string) (Method, bool)
	// 獲取類型方法集里導(dǎo)出的方法個(gè)數(shù)
	NumMethod() int
	// 類型名稱
	Name() string
	// 返回類型所在的路徑,如:encoding/base64
	PkgPath() string
	// 返回類型的大小,和 unsafe.Sizeof 功能類似
	Size() uintptr
	// 返回類型的字符串表示形式
	String() string
	// 返回類型的類型值
	Kind() Kind
	// 類型是否實(shí)現(xiàn)了接口 u
	Implements(u Type) bool
	// 是否可以賦值給 u
	AssignableTo(u Type) bool
	// 是否可以類型轉(zhuǎn)換成 u
	ConvertibleTo(u Type) bool
	// 類型是否可以比較
	Comparable() bool
	// 下面這些函數(shù)只有特定類型可以調(diào)用
	// 如:Key, Elem 兩個(gè)方法就只能是 Map 類型才能調(diào)用
	// 類型所占據(jù)的位數(shù)
	Bits() int
	// 返回通道的方向,只能是 chan 類型調(diào)用
	ChanDir() ChanDir
	// 返回類型是否是可變參數(shù),只能是 func 類型調(diào)用
	// 比如 t 是類型 func(x int, y ... float64)
	// 那么 t.IsVariadic() == true
	IsVariadic() bool
	// 返回內(nèi)部子元素類型,只能由類型 Array, Chan, Map, Ptr, or Slice 調(diào)用
	Elem() Type
	// 返回結(jié)構(gòu)體類型的第 i 個(gè)字段,只能是結(jié)構(gòu)體類型調(diào)用
	// 如果 i 超過了總字段數(shù),就會 panic
	Field(i int) StructField
	// 返回嵌套的結(jié)構(gòu)體的字段
	FieldByIndex(index []int) StructField
	// 通過字段名稱獲取字段
	FieldByName(name string) (StructField, bool)
	// FieldByNameFunc returns the struct field with a name
	// 返回名稱符合 func 函數(shù)的字段
	FieldByNameFunc(match func(string) bool) (StructField, bool)
	// 獲取函數(shù)類型的第 i 個(gè)參數(shù)的類型
	In(i int) Type
	// 返回 map 的 key 類型,只能由類型 map 調(diào)用
	Key() Type
	// 返回 Array 的長度,只能由類型 Array 調(diào)用
	Len() int
	// 返回類型字段的數(shù)量,只能由類型 Struct 調(diào)用
	NumField() int
	// 返回函數(shù)類型的輸入?yún)?shù)個(gè)數(shù)
	NumIn() int
	// 返回函數(shù)類型的返回值個(gè)數(shù)
	NumOut() int
	// 返回函數(shù)類型的第 i 個(gè)值的類型
	Out(i int) Type
        // 返回類型結(jié)構(gòu)體的相同部分
	common() *rtype
	// 返回類型結(jié)構(gòu)體的不同部分
	uncommon() *uncommonType
}
type Value struct {
    typ *rtype
    ptr unsafe.Pointer
    flag
}

反射的實(shí)現(xiàn)和interface的組成很相似,都是由“類型”和“數(shù)據(jù)值”構(gòu)成,但是值得注意的是:interface的“類型”和“數(shù)據(jù)值”是在“一起的”,而反射的“類型”和“數(shù)據(jù)值”是分開的。

TypeValue提供了非常多的方法:例如獲取對象的屬性列表、獲取和修改某個(gè)屬性的值、對象所屬結(jié)構(gòu)體的名字、對象的底層類型(underlying type)等等

Go中的反射,在使用中最核心的就兩個(gè)函數(shù):

  • reflect.TypeOf(x)
  • reflect.ValueOf(x)

這兩個(gè)函數(shù)可以分別將給定的數(shù)據(jù)對象轉(zhuǎn)化為以上的TypeValue。這兩個(gè)都叫做反射對象

3. 如何通過反射對象來修改原數(shù)據(jù)對象的值?

在Go中,任何函數(shù)的參數(shù)都是值的拷貝,而非原數(shù)據(jù)。

反射函數(shù)reflect.ValueOf()也不例外。我們目前得到的反射對象,都是原對象的copy的反射對象,而非原對象本身,所以不可以修改到原對象.

那如何修改呢?

首先,在Go中要想讓函數(shù)“有副作用“,傳值必須傳指針類型的。

var x float64 = 5.7
v := reflect.ValueOf(&x)

時(shí)還不行,因?yàn)檫@樣反射對象對應(yīng)的是原數(shù)據(jù)對象的指針類型,必須要拿到當(dāng)前類型的值類型(*v)。 Go提供了另外一個(gè)方法Elem()

p := v.Elem()
fmt.Println(p.CanSet()) // true

p.SetFloat(6.6)
fmt.Println(x) // 6.6

經(jīng)過以上操作,就可以修改原數(shù)據(jù)了,完整過程如下:

var x float64 = 5.7
v := reflect.ValueOf(&x)
p := v.Elem()
fmt.Println(p.CanSet()) // true
p.SetFloat(6.6)
fmt.Println(x) // 6.6

到此這篇關(guān)于Go反射底層原理及數(shù)據(jù)結(jié)構(gòu)解析的文章就介紹到這了,更多相關(guān) Go反射原理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring Boot(二)之web綜合開發(fā)

    Spring Boot(二)之web綜合開發(fā)

    本篇文章為大家介紹spring boot的其它特性(有些未必是spring boot體系桟的功能,但是是spring特別推薦的一些開源技術(shù)本文也會介紹),對了這里只是一個(gè)大概的介紹,特別詳細(xì)的使用我們會在其它的文章中來展開說明
    2017-05-05
  • JAVA如何自動下載SSL證書并導(dǎo)入到本地

    JAVA如何自動下載SSL證書并導(dǎo)入到本地

    這篇文章主要介紹了JAVA如何自動下載SSL證書并導(dǎo)入到本地問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • window版 IntelliJ IDEA 快捷鍵圖文教程

    window版 IntelliJ IDEA 快捷鍵圖文教程

    本文通過圖文并茂的形式給大家介紹了window版 IntelliJ IDEA 快捷鍵的操作方法,需要的朋友參考下吧
    2018-02-02
  • Java Jedis NOAUTH Authentication required問題解決方法

    Java Jedis NOAUTH Authentication required問題解決方法

    這篇文章主要介紹了Java Jedis NOAUTH Authentication required問題解決方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-07-07
  • SpringBoot讀取properties中文亂碼解決方案

    SpringBoot讀取properties中文亂碼解決方案

    本文主要介紹了在Spring?Boot中讀取帶有中文字符串的application.properties文件時(shí)遇到亂碼問題的解決方案,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-12-12
  • SpringBoot中pom.xml配置詳解

    SpringBoot中pom.xml配置詳解

    pom.xml是Maven項(xiàng)目的核心配置文件,用于管理項(xiàng)目的依賴、插件、構(gòu)建配置等,在Spring Boot項(xiàng)目中,pom.xml文件也扮演著重要的角色,本文將給大家詳細(xì)介紹一下SpringBoot中pom.xml配置,需要的朋友可以參考下
    2023-09-09
  • Java語言實(shí)現(xiàn)掃雷游戲(1)

    Java語言實(shí)現(xiàn)掃雷游戲(1)

    這篇文章主要為大家詳細(xì)介紹了Java語言實(shí)現(xiàn)的掃雷游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-04-04
  • SpringBoot集成WebSocket的兩種方式(JDK內(nèi)置版和Spring封裝版)

    SpringBoot集成WebSocket的兩種方式(JDK內(nèi)置版和Spring封裝版)

    這篇文章主要介紹了SpringBoot集成WebSocket的兩種方式,這兩種方式為JDK內(nèi)置版和Spring封裝版,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-06-06
  • 解決idea不顯示Services工具欄的問題

    解決idea不顯示Services工具欄的問題

    這篇文章主要介紹了解決idea不顯示Services工具欄的問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • springboot2.x默認(rèn)使用的代理是cglib代理操作

    springboot2.x默認(rèn)使用的代理是cglib代理操作

    這篇文章主要介紹了springboot2.x默認(rèn)使用的代理是cglib代理操作,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08

最新評論

营山县| 沙雅县| 赤水市| 乌鲁木齐市| 洛阳市| 岳阳市| 大埔区| 普安县| 陈巴尔虎旗| 顺义区| 前郭尔| 南丹县| 景泰县| 民勤县| 南乐县| 伊吾县| 衡阳县| 溧水县| 邻水| 南昌县| 东光县| 张家界市| 大关县| 高雄县| 田东县| 柳林县| 钟山县| 涟水县| 上思县| 会同县| 盐山县| 周宁县| 青田县| 安国市| 民勤县| 永靖县| 库车县| 贵定县| 溧阳市| 高青县| 武山县|