Golang基礎(chǔ)筆記十六之反射
本文首發(fā)于公眾號:Hunter后端
原文鏈接:Golang基礎(chǔ)筆記十六之反射
反射可以用于程序在運行時檢查、修改自身類型和值,主要通過 reflect 包實現(xiàn)。
首先,我們提出一個需求,要打印出一個結(jié)構(gòu)體 struct 的各個字段及其對應(yīng)的標簽數(shù)據(jù),按照當(dāng)前的筆記內(nèi)容是無法解決該問題的,但是我們可以使用反射操作來完成。
以下是本篇筆記目錄:
- 變量的類型和值
- 修改變量的值
- 遍歷結(jié)構(gòu)體字段
- 動態(tài)調(diào)用函數(shù)
1、變量的類型和值
先引入 reflect 模塊:
import (
"reflect"
)
我們可以通過 reflect.TypeOf() 獲取變量的類型:
var x float64 = 3.5
t := reflect.TypeOf(x)
返回的 t 是 Type 接口,我們可以進一步調(diào)用 t 的方法來獲取類型信息:
// 變量的類型名稱:
fmt.Println("x 的類型名稱是: ", t.Name())
// 判斷類型的類別:
fmt.Println("x 的類型是否是 float64: ", t.Kind() == reflect.Float64)
獲取變量的值信息:
v := reflect.ValueOf(x)
fmt.Println("value: ", v.Float() == 3.5)
2、修改變量的值
如果要修改這個變量的值,我們需要用到指針,以下是操作示例:
var x float64 = 3.5
// 這里獲取的是變量的地址的值,如果直接 reflect.ValueOf(x) 獲取的是 x 的副本
p := reflect.ValueOf(&x)
// Elem() 方法獲取指針指向的實際值,是解引用的操作
v := p.Elem()
// 重新賦值的操作
v.SetFloat(4.9)
fmt.Println("new value: ", x)
3、遍歷結(jié)構(gòu)體字段
我們先定義一個結(jié)構(gòu)體如下:
type Person struct {
Id int `json:"id" form:"id"`
Name string `json:"name"`
}
打印一個 Person 示例各個字段的名稱及其值的操作如下:
p := Person{
Id: 1,
Name: "hunter",
}
t := reflect.TypeOf(p)
v := reflect.ValueOf(p)
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
value := v.Field(i)
fmt.Printf("field_name:%s, field_type:%s, value:%v\n", field.Name, field.Type, value.Interface())
}
在這里,我們通過 t.NumField() 方法獲取到 p 的字段個數(shù),并使用 t.Field(i) 和 v.Field(i) 獲取到對應(yīng)字段類型和值。
接著對于每個 field 和 value,我們可以打印出對應(yīng)的字段名稱,字段類型和值。
我們還可以使用 field.Tag.Get() 的方式獲取到字段標簽的值:
fmt.Printf("json_tag:%s, form_tag:%s\n", field.Tag.Get("json"), field.Tag.Get("form"))
如果后續(xù)我們介紹 Golang 的 validator 模塊,可以了解到,validator 就是通過 struct 定義的標簽使用反射來對字段值進行驗證的。
4、動態(tài)調(diào)用函數(shù)
我們還可以使用反射來動態(tài)調(diào)用函數(shù),比如某個函數(shù)如下:
func Add(a, b int) int {
return a + b
}
使用反射動態(tài)調(diào)用的操作如下:
func main() {
targetFunc := reflect.ValueOf(Add)
args := []reflect.Value{reflect.ValueOf(2), reflect.ValueOf(5)}
result := targetFunc.Call(args)
fmt.Println("動態(tài)調(diào)用 Add 函數(shù),result: ", result[0].Int())
}
注意:雖然反射可以為我們提供一些便利的操作,但是代碼的可讀性和可維護性會降低,且會降低性能,需要在實際生產(chǎn)中謹慎使用。

浙公網(wǎng)安備 33010602011771號