Go反射指南

概念:

官方對此有個非常簡明的介紹,兩句話耐人尋味:

  1. 反射提供一種讓程序檢查自身結構的能力
  2. 反射是困惑的源泉

第1條,再精確點的描述是“反射是一種檢查interface變量的底層類型和值的機制”。 第2條,很有喜感的自嘲,不過往后看就笑不出來了,因為你很可能產生困惑。

reflect 實現了運行時的反射能力,能夠讓程序操作不同類型的對象。反射包中有兩對非常重要的函數和類型,兩個函數分別是:

  • reflect.TypeOf()? ?能獲取類型信息;
  • reflect.ValueOf()?能獲取數據的運行時表示;

只有這么簡單嗎?當然不是,請繼續閱讀。

引出:

其實了解反射的第一步,應從interface入手,因為反射與接口存在著千絲萬縷的關系。

如下是一段interface的源碼

type iface struct {tab  *itabdata unsafe.Pointer
}// layout of Itab known to compilers
// allocated in non-garbage-collected memory
// Needs to be in sync with
// ../cmd/compile/internal/gc/reflect.go:/^func.dumptypestructs.
type itab struct {inter  *interfacetype_type  *_typelink   *itabbad    int32inhash int32      // has this itab been added to hash?fun    [1]uintptr // variable sized
}

看不懂也沒關系,我對其大致簡化一番,從reflect角度再來看看,并思考從iface中看到的字段:

type I interface{// 方法集
}
type iface struct{typ reflect.Type   // 儲存類型信息val reflect.Value  // 儲存實際值
}

之所以引出interface,是因為想說interface類型有個(value,type)對,而反射就是檢查interface的這個(value, type)對的。具體一點說就是Go提供一組方法提取interface的value,提供另一組方法提取interface的type。

  • reflect.Type 提供一組接口處理interface的類型,即(value, type)中的type
  • reflect.Value 提供一組接口處理interface的值,即(value, type)中的value

下面會提到反射對象,所謂反射對象即反射包里提供的兩種類型的對象。

  • reflect.Type 類型對象
  • reflect.Value 類型對象

三大法則:

第一法則:

interface{}?變量,可以反射出反射對象;

下面示例,看看是如何通過反射獲取一個變量的值和類型的:

package mainimport ("fmt""reflect"
)func main() {var x float64 = 3.4t := reflect.TypeOf(x)  //t is reflext.Typefmt.Println("type:", t)v := reflect.ValueOf(x) //v is reflext.Valuefmt.Println("value:", v)
}運行如下:
type: float64
value: 3.4
是不是疑惑了,明明是上述是x->reflect類型,卻依然說是 interface{} --變為--> reflect類型呢?這是因為,在TypeOf 與 ValueOf 內部,自動將 值類型,轉化為了 接口類型。

?

第二法則:

從反射對象可以獲取?interface{}?變量;

package mainimport ("fmt""reflect"
)func main() {var x float64 = 3.4v := reflect.ValueOf(x) //v is reflext.Valuevar y float64 = v.Interface().(float64)fmt.Println("value:", y)
}

1、用reflect.ValueOf(x) 獲取,value值。

2、v.Interface() 轉化成接口。

3、類型斷言轉化成,對應的基本類型

?

第三法則:

要修改反射對象,其值必須可設置。

通過反射可以將interface類型變量轉換成反射對象,可以使用該反射對象設置其持有的值。在介紹何謂反射對象可修改前,先看一下失敗的例子:

package mainimport ("reflect"
)func main() {var x float64 = 3.4v := reflect.ValueOf(x)v.SetFloat(7.1) // Error: will panic.
}如下代碼,通過反射對象v設置新值,會出現panic。報錯如下:panic: reflect: reflect.Value.SetFloat using unaddressable value

錯誤原因即是v是不可修改的。

反射對象失敗,取決于是否可以修改其儲存的值。回想一下函數傳參時,是傳值還是傳址,就不難理解上例中為何失敗。

上例中,傳入 reflect.ValueOf() 函數的其實是x的值,而非x本身。即通過v修改其值是無法影響x的,也即是無效的修改,所以 golang 會報錯。

想到此處,即可明白,如果構建v時使用x的地址就可實現修改了,但此時v代表的是指針地址,我們要設置的是指針所指向的內容,也即我們想要修改的是*v。 那怎么通過v修改x的值呢?

reflect.Value 提供了 Elem() 方法,可以獲得指針向指向的Value 。看如下代碼:

package mainimport (
"reflect""fmt"
)func main() {var x float64 = 3.4v := reflect.ValueOf(&x)v.Elem().SetFloat(7.1)fmt.Println("x :", v.Elem().Interface())
}

1、調用reflect.ValueOf 獲取變量指針。

2、調用 reflect.Value.Elem 獲取指針指向的變量。

3、調用 reflect.Value.SetFloat() 更新變量。

總結:

以上為本篇博客精華內容,如有不妥,請及時私信聯系我,斟酌之后必加以糾正。

待后續深入學習時,會轉回繼續修改。

參考內容:

1、《Go專家編程》

2、《Go語言設計與實踐》

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/67199.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/67199.shtml
英文地址,請注明出處:http://en.pswp.cn/web/67199.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

第26篇 基于ARM A9處理器用C語言實現中斷<二>

Q:基于ARM A9處理器怎樣編寫C語言工程,使用按鍵中斷將數字顯示在七段數碼管上呢? A:基本原理:主程序需要首先調用子程序set_A9_IRQ_stack()初始化IRQ模式的ARM A9堆棧指針;然后主程序調用子程序config_GIC…

基于GS(Gaussian Splatting)的機器人Sim2Real2Sim仿真平臺

項目地址:RoboGSim 背景簡介 已有的數據采集方法中,遙操作(下左)是數據質量高,但采集成本高、效率低下;傳統仿真流程成本低(下右),但真實度(如紋理、物理&…

「 機器人 」利用沖程對稱性調節實現仿生飛行器姿態與方向控制

前言 在仿生撲翼飛行器中,通過改變沖程對稱性這一技術手段,可以在上沖與下沖兩個階段引入不對稱性,進而產生額外的力或力矩,用于實現俯仰或其他姿態方向的控制。以下從原理、在仿生飛行器中的應用和典型實驗示例等方面進行梳理與闡述。 1. 沖程對稱性原理 1.1 概念:上沖與…

MongoDB部署模式

目錄 單節點模式(Standalone) 副本集模式(Replica Set) 分片集群模式(Sharded Cluster) MongoDB有多種部署模式,可以根據業務需求選擇適合的架構和部署方式。 單節點模式(Standa…

微服務搭建----springboot接入Nacos2.x

springboot接入Nacos2.x nacos之前用的版本是1.0的,現在重新搭建一個2.0版本的,學如逆水行舟,不進則退,廢話不多說,開搞 1、 nacos2.x搭建 1,首先第一步查詢下項目之間的版本對照,不然后期會…

react-native網絡調試工具Reactotron保姆級教程

在React Native開發過程中,調試和性能優化是至關重要的環節。今天,就來給大家分享一個非常強大的工具——Reactotron,它就像是一個貼心的助手,能幫助我們更輕松地追蹤問題、優化性能。下面就是一份保姆級教程哦! 一、…

npm啟動前端項目時報錯(vue) error:0308010C:digital envelope routines::unsupported

vue 啟動項目時,npm run serve 報下面的錯: error:0308010C:digital envelope routines::unsupported at new Hash (node:internal/crypto/hash:67:19) at Object.createHash (node:crypto:133:10) at FSReqCallback.readFileAfterClose [as on…

改進候鳥優化算法之三:引入自適應策略的候鳥優化算法(AS-MBO)

引入自適應策略的候鳥優化算法(Migrating Birds Optimization with Adaptive Strategy,簡稱AS-MBO)是對傳統候鳥優化算法(Migrating Birds Optimization,MBO)的一種改進。MBO算法本身是一種基于群體智能的元啟發式優化算法,其靈感來源于候鳥遷徙時的“V”字形飛行隊列,…

02-機器學習-核心概念

以下是機器學習核心概念的詳細梳理。 1. 機器學習三大范式 類型定義典型應用監督學習使用帶標簽的數據訓練模型,預測未知數據的標簽。分類(郵件垃圾過濾)、回歸(房價預測)無監督學習從無標簽的數據中發現隱藏模式或結…

Redis實戰(黑馬點評)——關于緩存(緩存更新策略、緩存穿透、緩存雪崩、緩存擊穿、Redis工具)

redis實現查詢緩存的業務邏輯 service層實現 Overridepublic Result queryById(Long id) {String key CACHE_SHOP_KEY id;// 現查詢redis內有沒有數據String shopJson (String) redisTemplate.opsForValue().get(key);if(StrUtil.isNotBlank(shopJson)){ // 如果redis的數…

算法-加油站問題

hello 大家好!今天開寫一個新章節,每一天一道算法題。讓我們一起來學習算法思維吧! function canCompleteCircuit(gas, cost) {// 加油站的總數const n gas.length;// 記錄總剩余油量,若總剩余油量小于 0,說明無法繞環…

訊飛繪鏡(ai生成視頻)技術淺析(二):大模型

1.訊飛星火大模型的基礎架構 2.自然語言處理(NLP)技術的具體實現 3.腳本生成的具體過程與模型公式 4.分鏡生成的具體過程與模型公式 5.視頻生成與編輯的技術細節 6.關鍵技術公式的詳細推導與解釋 一、訊飛星火大模型的基礎架構 訊飛星火大模型是基于Transformer架構的深…

【機器學習】深入探索SVM:支持向量機的原理與應用

目錄 🍔 SVM引入 1.1什么是SVM? 1.2支持向量機分類 1.3 線性可分、線性和非線性的區分 🍔 小結 學習目標 知道SVM的概念 🍔 SVM引入 1.1什么是SVM? 看一個故事,故事是這樣子的: 在很久以前的情人節&#xf…

pycharm 運行遠程環境問題 Error:Failed to prepare environment.

問題排查 拿到更詳細的報錯信息: Help > Diagnostic Tools > Debug Log Settings section: 添加下面的配置 com.intellij.execution.configurations.GeneralCommandLine 重顯報錯,我這里是再次運行代碼打開 Help | Collect Logs and Diagnosti…

一組開源、免費、Metro風格的 WPF UI 控件庫

前言 今天大姚給大家分享一個開源、免費、Metro風格的 WPF UI 控件庫:MahApps.Metro。 項目介紹 MahApps.Metro 是一個開源、免費、Metro風格的 WPF UI 控件庫,提供了現代化、平滑和美觀的控件和樣式,幫助開發人員輕松創建具有現代感的 Win…

讀寫和解析簡單的 nc 文件

NetCDF 文件格式在氣象數據工程領域占據著舉足輕重的地位,其結構靈活、強兼容性等優勢使其成為該領域的一個標準。無論是從事學術研究還是工程實踐,掌握這種數據格式變得越發重要。其次,我注意到目前社區中氣象編程大多數課程都聚焦于某個特定…

Mac m1,m2,m3芯片使用nvm安裝node14報錯

使用nvm安裝了node 12/16/18都沒有問題,到14就報錯了。第一次看到這個報錯有點懵,查詢資料發現是Mac芯片的問題。 Issue上提供了兩個方案: 1、為了在arm64的Mac上安裝node 14,需要使用Rosseta,可以通過以下命令安裝 …

【計算機網絡】host文件

host文件的主要功能: 域名解析 本地映射:host文件的主要功能是將**域名映射到相應的 IP 地址**。當計算機需要訪問一個網站或服務時,它會首先在 host文件中查找該域名對應的 IP 地址。如果在 host文件中找到了匹配的域名和 IP 地址映射&…

vue3中customRef的用法以及使用場景

1. 基本概念 customRef 是 Vue3 提供的用于創建自定義響應式引用的 API,允許顯式地控制依賴追蹤和觸發響應。它返回一個帶有 get 和 set 函數的工廠函數來自定義 ref 的行為。 1.1 基本語法 import { customRef } from vuefunction createCustomRef(value) {retu…

周末總結(2024/01/25)

工作 人際關系核心實踐: 要學會隨時回應別人的善意,執行時間控制在5分鐘以內 堅持每天早會打招呼 遇到接不住的話題時拉低自己,抬高別人(無陰陽氣息) 朋友圈點贊控制在5min以內,職場社交不要放在5min以外 職場的人際關系在面對利…