淺談go反射

来源:https://www.cnblogs.com/shashark/archive/2023/10/24/17784584.html
-Advertisement-
Play Games

基本概念 支持反射的語言可以在程式編譯期將變數的反射信息,如欄位名稱、類型信息、結構體信息等整合到可執行文件中,並給程式提供介面訪問反射信息,這樣就可以在程式運行期獲取類型的反射信息,並且有能力修改它們。 Go語言提供了 reflect 包來訪問程式的反射信息。 Refelct解析 Refelct包 ...


基本概念
支持反射的語言可以在程式編譯期將變數的反射信息,如欄位名稱、類型信息、結構體信息等整合到可執行文件中,並給程式提供介面訪問反射信息,這樣就可以在程式運行期獲取類型的反射信息,並且有能力修改它們。

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

Refelct解析
Refelct包 定義了兩個重要的類型 Type 和 Value,任意介面在反射中都可以理解為 由 reflect.Type 和 reflect.Value 兩部分組成 。簡單來說,go 的介面是由兩部分組成的,一部分是類型信息,另一部分是數據信息
eg
var a=1
var b interface{}=a
對於 這個例子,b 的類型信息是 int,數據信息是 1,這兩部分信息都是存儲在 b 裡面的。b 的記憶體結構如下:

而 b實際上是一個空介面,也就是說一個 interface{} 中實際上既包含了變數的類型信息,也包含了類型的數據

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 類型變數轉換成反射對象。
  2. 反射可以將反射對象還原成 interface 對象。
  3. 如果要修改反射對象,那麼反射對象必須是可設置的(CanSet)。

將 interface 類型變數轉換成反射對象
我們可以通過 reflect.TypeOf 和 reflect.ValueOf 來獲取到一個變數的反射類型和反射值。
var a = 1
typeOfA := reflect.TypeOf(a)
valueOfA := reflect.ValueOf(a)

將反射對象還原成 interface 對象。
我們可以通過 reflect.Value.Interface 來獲取到反射對象的 interface 對象,也就是傳遞給 reflect.ValueOf 的那個變數本身。 不過返回值類型是 interface{},所以我們需要進行類型斷言。
i := valueOfA.Interface()
fmt.Println(i.(int))

修改反射對象
通過 reflect.Value.CanSet 來判斷一個反射對象是否是可設置的。如果是可設置的,我們就可以通過 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

那什麼情況下一個反射對象是可設置的呢?前提是這個反射對象是一個指針,然後這個指針指向的是一個可設置的變數 .
在上面這個例子中,v.CanSet() 返回的是 false,而 v.Elem().CanSet() 返回的是 true。
在這裡,v是一根指針,但是v.Elem()才是v這根指針指向的值。Elem方法是一個解引用的作用。對於這個指針本身,我們修改它是沒有意義的,我們可以設想一下, 如果我們修改了指針變數(也就是修改了指針變數指向的地址),那會發生什麼呢?那樣我們的指針變數就不是指向 x 了, 而是指向了其他的變數,這樣就不符合我們的預期了。所以 v.CanSet() 返回的是 false。
而 v.Elem().CanSet() 返回的是 true。這是因為 v.Elem() 才是 x 本身,通過 v.Elem() 修改 x 的值是沒有問題的

Elem()
refelct.Value中的Elem
reflect.Value 的 Elem 方法的作用是獲取指針指向的值,或者獲取介面的動態值。
對於指針很好理解,其實作用類似解引用。而對於介面,還是要回到 interface 的結構本身,因為介面里包含了類型和數據本身,所以 Elem 方法就是獲取介面的數據部分(也就是 iface 或 eface 中的 data 欄位)。
refelct.Type中的Elem
reflect.Type 的 Elem 方法的作用是獲取數組、chan、map、指針、切片關聯元素的類型信息,也就是說,對於 reflect.Type 來說, 能調用 Elem 方法的反射對象,必須是數組、chan、map、指針、切片中的一種,其他類型的 reflect.Type 調用 Elem 方法會 panic。
t1 := reflect.TypeOf([3]int{1, 2, 3}) // 數組 [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


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 目錄1. 什麼是內網穿透2. 實現背景3. 實現步驟3.1 安裝3.1.1 下載3.1.2 安裝服務端3.1.3 安裝客戶端4. Nginx 配置5. 官方文檔 1. 什麼是內網穿透 內網穿透(Port Forwarding)是一種網路技術,允許你將外部網路中的請求轉發到內部網路中的特定電腦或設備 ...
  • 本文主要介紹了python flask後端開發項目中的相關知識,包括flask項目結構、flask部署方式、前後端對接、後端介面測試工具。 ...
  • GeoIP2是一種IP地址定位庫,它允許開發人員根據`IP`地址查找有關位置和地理位置的信息。它使用`MaxMind`公司的IP地址資料庫,並提供一個方便的Python API。GeoIP2可以用於許多不同的應用程式,例如網站分析、廣告定位和身份驗證。GeoIP2提供了許多不同的信息,例如國家、城市... ...
  • Java替換RequstBody和RequestParam參數的屬性 本文主要講解在Java環境中如何替換RequestBody和RequestParam參數中的屬性 背景 近期由於接手的老項目中存在所有介面中新增一個加密串來給介面做一個加密效果(項目歷史原因,不方便上Jwt授權這套),所以就研究了 ...
  • `wmproxy`將用`Rust`實現`http/https`代理, `socks5`代理, 反向代理, 靜態文件伺服器,後續將實現`websocket`代理, 內外網穿透等, 會將實現過程分享出來, 感興趣的可以一起造個輪子法, 一些實現類nginx可能在rust會碰到的問題,一起探討下一些實現在... ...
  • 關註【TechLeadCloud】,分享互聯網架構、雲服務技術的全維度知識。作者擁有10+年互聯網服務架構、AI產品研發經驗、團隊管理經驗,同濟本復旦碩,復旦機器人智能實驗室成員,阿裡雲認證的資深架構師,項目管理專業人士,上億營收AI產品研發負責人。 一、引言 在軟體開發的世界里,開發環境的選擇與配 ...
  • 大家好,我是棧長。 今天分享一篇國內外程式員區別對比的好文: https://www.zhihu.com/question/497793332/answer/2216734220 原文作者是知乎的一位匿名用戶,個人感覺絕大部分內容寫的還是挺中肯的,沒有故意貶低或者抬高哪一邊。 下麵是正文。 我是在美 ...
  • 1.2 註釋 作用:在代碼中加一些說明和解釋,方便自己或其他程式員閱讀代碼 兩中格式 單行註釋: 通常放在一行代碼的上方,或者一條語句的末尾,對該行代碼說明 // 這樣的是單行註釋 多行註釋: 通常放在一段代碼的上方,對該段代碼做整體說明 /* 這種的是多行註釋 可以寫好多行 */ 提示:編譯器在編 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...