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

Go反射底層原理及數(shù)據(jù)結構解析

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

1. 反射的引入與介紹

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

需要反射的 2 個常見場景:

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

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

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

image.png

數(shù)據(jù)interface中保存有結構數(shù)據(jù),拿到該數(shù)據(jù)對應的內存地址,然后把該數(shù)據(jù)轉成interface,通過查看interface中的類型結構,就可以知道該數(shù)據(jù)的結構了,其實以上就是Go反射通俗的原理。

image.png

2. 反射的數(shù)據(jù)結構

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

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

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

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

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

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

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

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

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

那如何修改呢?

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

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

時還不行,因為這樣反射對象對應的是原數(shù)據(jù)對象的指針類型,必須要拿到當前類型的值類型(*v)。 Go提供了另外一個方法Elem()

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

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

經過以上操作,就可以修改原數(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

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

相關文章

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

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

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

    JAVA如何自動下載SSL證書并導入到本地

    這篇文章主要介紹了JAVA如何自動下載SSL證書并導入到本地問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    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問題解決方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-07-07
  • SpringBoot讀取properties中文亂碼解決方案

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

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

    SpringBoot中pom.xml配置詳解

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

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

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

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

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

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

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

    springboot2.x默認使用的代理是cglib代理操作

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

最新評論

南郑县| 自贡市| 敦煌市| 中西区| 昌平区| 合江县| 天长市| 西畴县| 延寿县| 聂拉木县| 永年县| 华坪县| 西盟| 江西省| 大连市| 赣州市| 邓州市| 社旗县| 岳阳县| 潮安县| 达州市| 札达县| 平利县| 宜良县| 阆中市| 宝丰县| 驻马店市| 郑州市| 阿尔山市| 卓资县| 城固县| 宜春市| 隆德县| 合肥市| 曲麻莱县| 赣州市| 拉萨市| 清远市| 运城市| 顺昌县| 沙洋县|