網站首頁 編程語言 正文
reflect 反射包
針對反射,Go
提供了 reflect
包,使用這個包里的函數可以在程序運行時獲取和更新未知變量的值,操作未知變量的方法等。
reflect
包核心的兩個重要類型:
-
reflect.Type
:Type
是一個接口,不同數據類型有著不同的結構體實現。這個接口用于操作變量的類型信息,類型的信息只能讀取。 -
reflect.Value
:Value
是一個結構體,通過這個結構體可以操作變量的值。
TypeOf(i) 和 ValueOf(i)
-
reflect.TypeOf(i any) Type
:獲取變量的類型,返回一個reflect.Type
類型。 -
reflect.ValueOf(i any) Value
:獲取變量的值,返回reflect.Value
類型,通過Value
可以對獲取變量更多的信息。
案例1:獲取變量的類別和類型信息
import ( "fmt" "reflect" ) type User struct { Name string } func main() { user := User{ Name: "cmy", } func4Reflect(user) } func func4Reflect(data any) { typ := reflect.TypeOf(data) fmt.Println("類別:", typ.Kind()) // 類別: struct fmt.Println("類型:", typ.Name()) // 類型: User }
- 通過
TypeOf()
函數獲取data
的類型信息,然后調用Kind()
和Name()
方法分別獲取data
變量的類別和類型信息。 - 根據返回結果可知,
Kind()
返回的是Go
的數據類型,而Name()
返回的是我們自定義的數據類型。 - 根據
Kind()
返回值的特點,可以用于判斷變量屬于 Go 的哪種數據類型,用于類型限制等場景。
案例2:修改基本數據類型變量的值
import ( "fmt" "reflect" ) func main() { num1 := 666 fmt.Println("num1 原值:", num1) func4Reflect(&num1) fmt.Println("num1 修改后的值:", num1) num2 := 0.5 fmt.Println("num2 原值:", num2) func4Reflect(&num2) fmt.Println("num2 修改后的值:", num2) str := "go" fmt.Println("str 原值:", str) func4Reflect(&str) fmt.Println("str 修改后的值:", str) } func func4Reflect(data any) { typ := reflect.TypeOf(data) val := reflect.ValueOf(data) switch typ.Elem().Kind() { case reflect.Int: val.Elem().SetInt(888) case reflect.Float64: val.Elem().SetFloat(3.14) case reflect.String: val.Elem().SetString("Golang") } }
通過 ValueOf()
函數獲取 data
變量的值信息,然后結合 reflect.Type.Kind()
方法,對不同類型的變量的值進行修改操作(只舉三種類型的例子):
-
int
類型 → 使用SetInt(val)
方法對值進行修改。 -
float64
→ 使用SetFloat(val)
方法對值進行修改。 -
string
類型 → 使用SetString(val)
方法對值進行修改。
data
必須是指針類型,否則無法通過反射修改。
由于是指針類型,因此需要調用 Elem()
方法獲取到指針指向的變量,才能修改變量的值。
案例3:通過反射獲取結構體的字段名、字段類型和字段的值
import ( "fmt" "reflect" ) type User struct { Name string Age int } func main() { user := User{ Name: "cmy", Age: 18, } func4Reflect(user) } func func4Reflect(data any) { typ := reflect.TypeOf(data) val := reflect.ValueOf(data) // 獲取結構體字段的數量 numField := val.NumField() for i := 0; i < numField; i++ { fmt.Println("字段名稱:", typ.Field(i).Name) fmt.Println("字段類型:", typ.Field(i).Type.Name()) fmt.Println("字段值:", val.Field(i).Interface()) fmt.Println("----------------------------") } }
- 首先通過
TypeOf()
和ValueOf()
獲取到結構體的類型信息和值信息。 - 其次通過
Value.NumField()
方法獲取到結構體字段的數量。 - 接著遍歷結構體的字段,通過
Type.Field(i)
方法,傳入索引,獲取到對應字段的類型信息,通過Name
屬性獲取字段名,Type.Name()
獲取字段類型。 - 最后通過
Value.Field(i)
方法,傳入索引,獲取到對應字段的值信息,通過Interface()
方法獲取字段實際的值。
小結
本文首先介紹了 reflect
包里兩個重要的類型 reflect.Type
和 reflect.Value
,簡單說明了它們的作用;其次介紹了TypeOf(i)
和 ValueOf(i)
兩個函數;最后通過三個案例介紹了它們的使用場景。
原文鏈接:https://juejin.cn/post/7173317932355846157
相關推薦
- 2023-01-12 Golang單元測試與斷言編寫流程詳解_Golang
- 2022-10-19 python列表[list]和元組(tuple)詳情_python
- 2022-12-07 org.apache.tomcat.util.http.fileupload.IOUtils報錯對應
- 2022-04-07 C++11時間日期庫chrono的使用_C 語言
- 2022-11-13 Python?argparse模塊實現解析命令行參數方法詳解_python
- 2022-05-26 Tomcat服務部署及優化的實現_Tomcat
- 2022-08-05 記一次使用EasyExcel出現Convert excel format exception.You
- 2022-03-30 C#算法之整數反轉_C#教程
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支