婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > 圖文詳解go語言反射實現原理

圖文詳解go語言反射實現原理

熱門標簽:福州鐵通自動外呼系統 地圖標注測試 智能電銷機器人營銷 濮陽自動外呼系統代理 澳門防封電銷卡 賺地圖標注的錢犯法嗎 烏魯木齊人工電銷機器人系統 長沙ai機器人電銷 廣東語音外呼系統供應商

Go反射的實現和 interfaceunsafe.Pointer 密切相關。如果對golang的 interface 底層實現還沒有理解,可以去看我之前的文章: Go語言interface底層實現 , unsafe.Pointer 會在后續的文章中做介紹。

(本文目前使用的Go環境是Go 1.12.9)

interface回顧

首先我們簡單的回顧一下interface的結構,總體上是:

細分下來分為有函數的 iface 和無函數的 eface (就是 interface{} );

無函數的 eface

有函數的 iface

靜態類型(static interface type)和動態混合類型(dynamic concrete type)

Go語言中,每個變量都有唯一個 靜態類型 ,這個類型是編譯階段就可以確定的。有的變量可能除了靜態類型之外,還會有 動態混合類型

例如以下例子:

//帶函數的interface
var r io.Reader 
tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0)
if err != nil {
 return nil, err
}
r = tty
//不帶函數的interface
var empty interface{}
empty = tty

有函數的 iface 的例子

我們一句一句來看:第1行, var r io.Reader

第4行至第七行就是簡單的賦值,得到一個 *os.File 的實例,暫且不看了。最后一句第十句 r = tty

無函數的 eface 的例子

我們接著往下看, var empty interface{}

最后是 empty = tty

但是記住:雖然有 動態混合類型 ,但是對外”表現”依然是靜態類型。

Go反射簡介

Go反射有三大法則:

//接口數據  =====》 反射對象
1. Reflection goes from interface value to reflection object.
//反射對象 ===> 接口數據
2. Reflection goes from reflection object to interface value.
// 倘若數據可更改,可通過反射對象來修改它
3. To modify a reflection object, the value must be settable.

Go 的反射就是對以上三項法則的實現。

Go的反射主要由兩部分組成: TypeValueTypeValue 是倆結構體:(這倆結構體具體內容可以略過不看,知道有這回事兒就行了)

Type:

type Type interface {
 Align() int
 FieldAlign() int
 Method(int) Method
 MethodByName(string) (Method, bool)
 NumMethod() int
 Name() string
 PkgPath() string
 Size() uintptr
 String() string
 Kind() Kind
 Implements(u Type) bool
 AssignableTo(u Type) bool
 ConvertibleTo(u Type) bool
 Comparable() bool
 Bits() int
 ChanDir() ChanDir
 IsVariadic() bool
 Elem() Type
 Field(i int) StructField
 FieldByIndex(index []int) StructField
 FieldByName(name string) (StructField, bool)
 FieldByNameFunc(match func(string) bool) (StructField, bool)
 In(i int) Type
 Key() Type
 Len() int
 NumField() int
 NumIn() int
 NumOut() int
 Out(i int) Type
 common() *rtype
 uncommon() *uncommonType
}

Value:

type Value struct {
 typ *rtype
 ptr unsafe.Pointer
 flag
}

你會發現反射的實現和interface的組成很相似,都是由“類型”和“數據值”構成,但是值得注意的是:interface的“類型”和“數據值”是在“一起的”,而反射的“類型”和“數據值”是分開的。

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

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

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

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

Reflection goes from interface value to reflection object(法則一)

給定一個數據對象,可以將數據對象轉化為反射對象 TypeValue

事例代碼:

package main

import (
 "fmt"
 "reflect"
)

func main() {
 var x float64 = 3.4

 t := reflect.TypeOf(x)
 v := reflect.ValueOf(x)

 fmt.Println("type:", t) //type: float64

 fmt.Println("value:", v.String()) //value: float64 Value>
 fmt.Println("type:", v.Type()) // type: float64
 fmt.Println("kind is float64:", v.Kind() == reflect.Float64) //kind is float64: true
 fmt.Println("value:", v.Float()) //value: 3.4

}

由代碼17行可以看出: Value 還可以獲取到當前數據值的 Type

所以,法則一的圖應為:

Reflection goes from reflection object to interface value.(法則二)

給定的反射對象,可以轉化為某種類型的數據對象。即法則一的逆向。

注意 Type 是沒法逆向轉換的,仔細想想也合理,如果可逆類型轉化成什么呢?(#^.^#)

承接法則一的代碼:

package main
import (
 "fmt"
 "reflect"
)
func main() {
 var x float64 = 3.4
 t := reflect.TypeOf(x)
 v := reflect.ValueOf(x)
 ...
 o := v.Interface().(float64) // 法則2代碼
 fmt.Println(o)
}

To modify a reflection object, the value must be settable.(法則三)

法則三是說:通過反射對象,可以修改原數據中的內容。

這里說的反射對象,是指 Value ,畢竟 Type 只是表示原數據的類型相關的內容,而 Value 是對應著原數據對象本身。

在目前以上的所有例子中,反射得到的 Value 對象的修改,都是無法直接修改原數據對象的。

package main
import (
 "fmt"
 "reflect"
)
func main() {
 var x float64 = 3.4
 t := reflect.TypeOf(x)
 v := reflect.ValueOf(x)
 ....
 o := v.Interface().(float64)
 fmt.Println(o)
 v.SetFloat(5.4) //此行會報錯
 fmt.Println(x)
}

這段代碼20行會報一個panic

reflect: reflect.Value.SetFloat using unaddressable value

這句話的意思并不是地址不可達,而是:對象 v 不可設置( settable )。

我們可以通過 Value 結構體的 CanSet() 方法來查看是否可以設置修改新值。

通過以下代碼可以知道 CanSet() 返回值是false。

fmt.Println(v.CanSet()) // false

如何通過反射對象來修改原數據對象的值呢?

如何才能可以通過反射對象來修改原數據對象的值或者說為什么不能設置呢?

原因簡單且純粹:在Go中,任何函數的參數都是值的拷貝,而非原數據。

反射函數 reflect.ValueOf() 也不例外。我們目前得到的反射對象,都是原對象的copy的反射對象,而非原對象本身,所以不可以修改到原對象;即使可以修改,修改一個傳參時候的副本,也毫無意義,不如報錯兒。Go反射第三法則中的制定的 settable 屬性就由此而來,還延伸出了類似于 CanSet() 的方法。

那如何修改呢?

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

...

var x float64 = 3.4
v := reflect.ValueOf(x)

...

此時還不行,因為這樣反射對象對應的是原數據對象的指針類型,必須要拿到當前類型的值類型(*v),如何做?

Go提供了另外一個方法 Elem()

...
var x float64 = 3.4
v := reflect.ValueOf(x)
p := v.Elem()
fmt.Println(p.CanSet()) // true
p.SetFloat(7.1)
fmt.Println(x) // 7.1

看以上代碼,就可以修改原數據了。

反射原理

不難發現,go的反射和interface在結構上是如此的相近!都分為兩部分:一部分是 Type 一部分是 value

反射會不會是比著interface來實現的?

反射是什么意思?反射的意思是在運行時,能夠動態知道給定數據對象的類型和結構,并有機會修改它!

現在一個數據對象,如何判斷它是什么結構?

數據interface中保存有結構數據呀,只要想辦法拿到該數據對應的內存地址,然后把該數據轉成interface,通過查看interface中的類型結構,就可以知道該數據的結構了呀~

其實以上就是Go反射通俗的原理。

圖可以展示為:

圖中結構中牽扯到的指針,都是 unsafe.Pointer 指針,具體這是個什么指針,后續的文章中會有介紹,在此,你就姑且認為是可以指向Go系統中任意數據的指針就可以。

源碼部分 (以下部分可以忽略,是我在查閱代碼時候遇到的一點點坑。)

我們來看看具體的源碼:源碼在”GO SDK/src/refelct“包中,具體主要是包中的”type.go”和”value.go”這兩個文件。

可以簡單的認為,反射的核心代碼,主要是 reflect.ValueOf()reflect.TypeOf() 這兩個函數。

先看類型轉換: reflect.TypeOf()

// TypeOf returns the reflection Type that represents the dynamic type of i.
// If i is a nil interface value, TypeOf returns nil.
func TypeOf(i interface{}) Type {
 eface := *(*emptyInterface)(unsafe.Pointer(i))
 return toType(eface.typ)
}

其中出現了兩種數據結構,一個是 Type ,一個是 emptyInterface

分別看看這兩者的代碼:

emptyInterface 在 ”GO SDK/src/reflect/value.go“文件中

// emptyInterface is the header for an interface{} value.
type emptyInterface struct {
 typ *rtype
 word unsafe.Pointer
}

// nonEmptyInterface is the header for an interface value with methods.
type nonEmptyInterface struct {
 // see ../runtime/iface.go:/Itab
 itab *struct {
  ityp *rtype // static interface type
  typ *rtype // dynamic concrete type
  hash uint32 // copy of typ.hash
  _ [4]byte
  fun [100000]unsafe.Pointer // method table
 }
 word unsafe.Pointer
}

仔細一看,是空接口和包含方法的interface的兩個結構體。且和 efaceiface 內容字段一致!不是有 efaceiface 了嗎?這兩者有什么不同??

經過查閱代碼,發現:

interface源碼(位于”Go SDK/src/runtime/runtime2.go“)中的 efaceiface 會和 反射源碼(位于”GO SDK/src/reflect/value.go“)中的 emptyInterfacenonEmptyInterface 保持數據同步!

總結

以上所述是小編給大家介紹的圖文詳解go語言反射實現原理,希望對大家有所幫助!

您可能感興趣的文章:
  • golang之反射和斷言的具體使用
  • 詳解Golang利用反射reflect動態調用方法
  • 淺談Go語言中的結構體struct & 接口Interface & 反射
  • Go語言學習筆記之反射用法詳解
  • Go語言中反射的正確使用
  • 談談Go語言的反射三定律
  • go語言通過反射獲取和設置結構體字段值的方法
  • Go語言中使用反射的方法

標簽:德州 阿克蘇 廣西 太原 貴陽 西雙版納 調研邀請 慶陽

巨人網絡通訊聲明:本文標題《圖文詳解go語言反射實現原理》,本文關鍵詞  圖文,詳解,語言,反射,實現,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《圖文詳解go語言反射實現原理》相關的同類信息!
  • 本頁收集關于圖文詳解go語言反射實現原理的相關信息資訊供網民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    亚洲一区二区三区自拍| 中文字幕乱码亚洲精品一区| 99久久精品国产导航| 国内精品伊人久久久久av影院| 日本成人中文字幕| 免费欧美在线视频| 久99久精品视频免费观看| 理论片日本一区| 国产精品一区二区在线看| 国产福利一区在线观看| 成人高清免费在线播放| 色悠悠亚洲一区二区| 欧美日韩一区不卡| 日韩欧美国产1| 国产欧美综合在线观看第十页| 国产精品国产三级国产aⅴ中文| 亚洲人吸女人奶水| 亚洲图片有声小说| 麻豆免费精品视频| 成人精品在线视频观看| 91福利在线观看| 精品美女在线播放| 亚洲三级免费观看| 奇米一区二区三区av| 国产成人精品网址| 欧美日韩一区二区三区免费看 | 成人免费视频网站在线观看| 不卡av电影在线播放| 欧洲一区二区av| 精品奇米国产一区二区三区| 日韩一区欧美小说| 奇米亚洲午夜久久精品| 99re这里只有精品视频首页| 欧美一级电影网站| 亚洲精品视频在线看| 激情偷乱视频一区二区三区| 在线观看免费视频综合| 久久精品夜夜夜夜久久| 亚洲线精品一区二区三区 | 亚洲妇熟xx妇色黄| 激情综合一区二区三区| 精品视频一区三区九区| 国产精品美女久久久久久 | 一本久道中文字幕精品亚洲嫩| 欧美精品一二三四| 综合激情成人伊人| 麻豆精品新av中文字幕| 欧美日韩一区二区在线视频| 国产视频一区不卡| 精品在线观看视频| 欧美日韩一区二区三区免费看 | 亚洲欧美成aⅴ人在线观看| 久久99精品视频| 91麻豆精品国产自产在线| 亚洲欧美另类综合偷拍| 岛国av在线一区| 2023国产一二三区日本精品2022| 视频一区国产视频| 在线观看网站黄不卡| 国产精品久久久久一区二区三区共| 激情图片小说一区| 欧美sm极限捆绑bd| 麻豆91在线看| 69p69国产精品| 视频一区免费在线观看| 欧美精品日韩综合在线| 亚洲黄色片在线观看| 成人sese在线| 国产精品久99| 99久久伊人精品| 国产精品传媒入口麻豆| 成人午夜激情在线| 中文字幕亚洲欧美在线不卡| 成人av在线观| 亚洲人成网站在线| 欧美日韩一卡二卡三卡 | 国产精品77777| 国产精品私房写真福利视频| 国产激情视频一区二区在线观看| 久久一日本道色综合| 国产精品综合一区二区三区| 欧美极品美女视频| 懂色av一区二区夜夜嗨| 国产精品二三区| 欧美做爰猛烈大尺度电影无法无天| 亚洲国产视频一区二区| 欧美性大战久久久久久久| 日韩电影在线免费观看| 精品国产伦理网| 在线观看欧美精品| 毛片不卡一区二区| 国产欧美一区二区在线| 91福利国产成人精品照片| 日韩精品电影一区亚洲| 久久久精品黄色| 色婷婷亚洲精品| 日韩二区三区在线观看| 国产亚洲一区二区在线观看| 一本久久综合亚洲鲁鲁五月天| 日本不卡在线视频| 欧美激情在线免费观看| 欧美日韩精品一区视频| 国产精品18久久久久| 一区二区不卡在线播放| 精品对白一区国产伦| 99综合影院在线| 日日摸夜夜添夜夜添精品视频| 久久众筹精品私拍模特| 欧美亚洲一区二区在线| 国产毛片一区二区| 亚洲18色成人| 1024成人网| 精品奇米国产一区二区三区| 在线观看免费视频综合| 国产剧情在线观看一区二区| 亚洲国产一区视频| 国产精品电影一区二区三区| 欧美电影免费提供在线观看| 一本一道综合狠狠老| 国产二区国产一区在线观看| 天堂久久久久va久久久久| 成人欧美一区二区三区1314| 精品久久99ma| 欧美一区永久视频免费观看| 一本大道av伊人久久综合| 精品亚洲成a人| 奇米888四色在线精品| 一区二区三区波多野结衣在线观看 | 国产精品三级av在线播放| 欧美成人综合网站| 欧美美女黄视频| 91成人在线精品| 97se狠狠狠综合亚洲狠狠| 成人午夜视频网站| 国产福利一区二区三区视频| 美女国产一区二区三区| 亚洲国产美女搞黄色| 亚洲午夜久久久久久久久电影院 | 日本欧美一区二区三区| 亚洲乱码国产乱码精品精小说| 日本一区二区免费在线| 久久精品亚洲乱码伦伦中文| 精品处破学生在线二十三| 日韩欧美国产系列| 欧美一区二区在线免费播放| 欧美日韩三级视频| 欧美日韩综合不卡| 欧美色综合影院| 欧美日韩精品一区二区三区蜜桃| 欧日韩精品视频| 欧美狂野另类xxxxoooo| 日韩一区二区免费在线观看| 日韩欧美国产午夜精品| 久久午夜羞羞影院免费观看| 国产午夜精品理论片a级大结局| 久久天天做天天爱综合色| 久久欧美一区二区| 亚洲国产高清在线观看视频| 中文字幕免费不卡| 亚洲天堂成人在线观看| 亚洲黄色免费网站| 视频一区视频二区在线观看| 久久电影网电视剧免费观看| 国产精品一线二线三线精华| 成人v精品蜜桃久久一区| 在线免费精品视频| 欧美一区二区三级| 国产亚洲精品福利| 亚洲丝袜另类动漫二区| 亚洲成人av电影在线| 蜜臀av性久久久久蜜臀aⅴ| 国产盗摄视频一区二区三区| 91在线免费播放| 337p亚洲精品色噜噜狠狠| 久久―日本道色综合久久| 国产精品久久三| 日韩av中文在线观看| 成人中文字幕合集| 精品视频一区三区九区| 国产亚洲成av人在线观看导航| 亚洲另类在线一区| 男女性色大片免费观看一区二区| 激情综合网天天干| 在线看国产一区二区| 久久蜜臀中文字幕| 一区二区免费在线播放| 国产成人在线看| 7777精品伊人久久久大香线蕉完整版 | 日韩一区中文字幕| 欧美aⅴ一区二区三区视频| 91亚洲永久精品| 日韩免费在线观看| 亚洲主播在线观看| 国产精品一品视频| 欧美一区二区国产| 亚洲女人的天堂| 国产精品2024| 欧美大黄免费观看| 日韩av在线播放中文字幕| 色乱码一区二区三区88|