Go 語言基礎系列(十二):反射

前言

本人從事 Go 語言開發多年,目前主要從事雲計算相關開發。

寫本公衆號的目的主要是對自己的過往知識進行梳理,也希望可以幫助大家學習~ 

後續會推出 _Go 語言源碼學習系列_和 web 開發系列等,歡迎大家關注。

今天我們來學習本系列的倒數第四篇:反射。請大家先記住一句話:反射是很多通用框架的基石。比如:Golang 的一些測試框架。

反射是一種機制:一種可以在運行狀態下,可以對與變量相關的值、類型以及方法等進行操作的機制。反射的學習是比較簡單的,主要的是理解這種思想,便於我們更高階的學習。在 Golang 中學習反射,主要是基於兩個重要的函數:reflect.TypeOf() 和 reflect.ValueOf()

思維邏輯圖如下:

下面我們從以上三個方面對 **反射 **進行相應的介紹

**   reflect.TypeOf()  **

前面我們提到,通過反射機制,我們可以獲得變量相關的值、類型、方法等信息;這一部分我們介紹首先獲取類型信息

Golang 中,通過調用 reflect 包中的 TypeOf() 獲取變量的類型信息

我們通過一個簡單的例子來看一下 TypeOf 函數的使用:

結果如下:

下面我們通過源碼進一步分析:

1)TypeOf 函數

TypeOf 函數將傳入的任何類型轉換爲其反射類型對象:Type 類型,而 Type 被定義爲一種接口:

而在 Type 接口裏定義了我們獲取變量相關信息的一些方法:

所以,當我們將任意類型的變量轉換爲 Type 接口類型後,可以調用其相關的函數實現對目標信息的獲取。本示例中,我們想獲得類型信息,所以調用其 Kind 函數便可獲取到,其他相關方法我們後續有部分涉及,大家有興趣的話可以都嘗試一下

  1. 本示例中,我們調用了 Kind 函數獲取類型信息,那麼作爲了解,Golang 中定義了哪些類型呢?源碼中定義如下:

如上所示,共計 27 種類型定義

示例:我們進一步以獲取某個結構體的字段的類型值爲例,對相關的方法進行演示:

結果如下:

分析:如上,我們通過 TypeOf 函數將結構體對象轉爲 Type 對象,再調用 FieldByName,NumField 以及 Field 等相關函數得到字段的相關信息,而字段相關的信息保存在 StructField 結構體裏,如下:

**   reflect.ValueOf()  **

如同 reflect.TypeOf() 獲取類型信息一樣方便,reflect.ValueOf() 函數可以很方便的獲取變量值信息

我們通過一個簡單示例演示如下:

結果如下:

源碼中,ValueOf 函數定義如下:

該函數將任意類型的輸入轉換爲其反射值對象,Value 被定義爲結構體

該結構體定義了許多值相關的方法,比如我們本例中調用的 Int() 方法

通過源碼註釋,我們知道:當 v 的類型爲 Int 類型時,返回其值,如果不是 Int 類型則 panic。還有很多其他類似的方法,大家也可以自己去實踐一下

下面我們進一步通過一個例子演示:

結果如下:

panic 的原因如下:Interface 方法不能被非導出字段調用

**   反射三定律  **

反射三定律其實在上文的介紹中,我們其實已經在使用了,這裏單獨抽離進行歸納介紹

定律 1:接口到反射類型的轉換

其實,接口到反射類型的轉換,就是我們上文介紹的兩個函數:reflect.TypeOf() 和 reflect.ValueOf(),它倆會將接口類型變量轉換爲反射類型變量

分別如下:

示例如下:

結果如下:

定律 2:反射到接口類型的轉換

定律 2 是說:我們可以將反射類型變量再轉換爲接口類型,而使用的方法就是上文中我們調用的 Interface() 方法

結果如下:

定律 3:修改反射類型對象

定律 3 是說:我們可以通過反射對變量值進行修改,但是變量值必須爲可設的(CanSet):可尋址(CanAddr),可導出(首字母大寫,不可匿名)

示例如下:

結果如下:

分析:對獲取的反射類型對象進一步通過 Elem 獲取其變量的值,然後對變量的值進行操作,由結果第一、二行對比可知,Elem 的作用相當於取指針類型變量的元素

總結:本篇主要介紹了反射機制,反射由於其靈活性廣泛應用於通用框架,然而魚與熊掌不可兼得,帶來的是效率上的損失,所以關於反射的使用要綜合考量,最後,通過一個基準測試的例子進一步說明效率上反射的損失,也爲下一篇做鋪墊

執行方式:go test -bench=.    結果如下:

分析:由最後一列可知,效率上變得很差

到此關於 Golang 文件操作相關內容的分享就結束了~

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/tqTDW2incmLm5upGJ7-NQQ