一文初探Go語言中的reflect反射包
reflect 反射包
針對反射,Go 提供了 reflect 包,使用這個包里的函數(shù)可以在程序運行時獲取和更新未知變量的值,操作未知變量的方法等。
reflect 包核心的兩個重要類型:
reflect.Type:Type是一個接口,不同數(shù)據(jù)類型有著不同的結(jié)構(gòu)體實現(xiàn)。這個接口用于操作變量的類型信息,類型的信息只能讀取。reflect.Value:Value是一個結(jié)構(gòu)體,通過這個結(jié)構(gòu)體可以操作變量的值。
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()函數(shù)獲取data的類型信息,然后調(diào)用Kind()和Name()方法分別獲取data變量的類別和類型信息。 - 根據(jù)返回結(jié)果可知,
Kind()返回的是Go的數(shù)據(jù)類型,而Name()返回的是我們自定義的數(shù)據(jù)類型。 - 根據(jù)
Kind()返回值的特點,可以用于判斷變量屬于 Go 的哪種數(shù)據(jù)類型,用于類型限制等場景。
案例2:修改基本數(shù)據(jù)類型變量的值
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() 函數(shù)獲取 data 變量的值信息,然后結(jié)合 reflect.Type.Kind() 方法,對不同類型的變量的值進行修改操作(只舉三種類型的例子):
int類型 → 使用SetInt(val)方法對值進行修改。float64→ 使用SetFloat(val)方法對值進行修改。string類型 → 使用SetString(val)方法對值進行修改。
data 必須是指針類型,否則無法通過反射修改。
由于是指針類型,因此需要調(diào)用 Elem() 方法獲取到指針指向的變量,才能修改變量的值。
案例3:通過反射獲取結(jié)構(gòu)體的字段名、字段類型和字段的值
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)
// 獲取結(jié)構(gòu)體字段的數(shù)量
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()獲取到結(jié)構(gòu)體的類型信息和值信息。 - 其次通過
Value.NumField()方法獲取到結(jié)構(gòu)體字段的數(shù)量。 - 接著遍歷結(jié)構(gòu)體的字段,通過
Type.Field(i)方法,傳入索引,獲取到對應字段的類型信息,通過Name屬性獲取字段名,Type.Name()獲取字段類型。 - 最后通過
Value.Field(i)方法,傳入索引,獲取到對應字段的值信息,通過Interface()方法獲取字段實際的值。
小結(jié)
本文首先介紹了 reflect 包里兩個重要的類型 reflect.Type 和 reflect.Value,簡單說明了它們的作用;其次介紹了TypeOf(i) 和 ValueOf(i) 兩個函數(shù);最后通過三個案例介紹了它們的使用場景。
到此這篇關(guān)于一文初探Go語言中的reflect反射包的文章就介紹到這了,更多相關(guān)Go語言reflect反射包內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
GoFrame?gtree樹形結(jié)構(gòu)的使用技巧示例
這篇文章主要為大家介紹了GoFrame?gtree樹形結(jié)構(gòu)的使用技巧示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-06-06

