動態

詳情 返回 返回

Golang基礎筆記十六之反射 - 動態 詳情

本文首發於公眾號:Hunter後端

原文鏈接:Golang基礎筆記十六之反射

反射可以用於程序在運行時檢查、修改自身類型和值,主要通過 reflect 包實現。

首先,我們提出一個需求,要打印出一個結構體 struct 的各個字段及其對應的標籤數據,按照當前的筆記內容是無法解決該問題的,但是我們可以使用反射操作來完成。

以下是本篇筆記目錄:

  1. 變量的類型和值
  2. 修改變量的值
  3. 遍歷結構體字段
  4. 動態調用函數

1、變量的類型和值

先引入 reflect 模塊:

import (
    "reflect"
)

我們可以通過 reflect.TypeOf() 獲取變量的類型:

var x float64 = 3.5

t := reflect.TypeOf(x)

返回的 t 是 Type 接口,我們可以進一步調用 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、遍歷結構體字段

我們先定義一個結構體如下:

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 的字段個數,並使用 t.Field(i)v.Field(i) 獲取到對應字段類型和值。

接着對於每個 field 和 value,我們可以打印出對應的字段名稱,字段類型和值。

我們還可以使用 field.Tag.Get() 的方式獲取到字段標籤的值:

fmt.Printf("json_tag:%s, form_tag:%s\n", field.Tag.Get("json"), field.Tag.Get("form"))

如果後續我們介紹 Golang 的 validator 模塊,可以瞭解到,validator 就是通過 struct 定義的標籤使用反射來對字段值進行驗證的。

4、動態調用函數

我們還可以使用反射來動態調用函數,比如某個函數如下:

func Add(a, b int) int {
    return a + b
}

使用反射動態調用的操作如下:

func main() {
    targetFunc := reflect.ValueOf(Add)

    args := []reflect.Value{reflect.ValueOf(2), reflect.ValueOf(5)}

    result := targetFunc.Call(args)
    fmt.Println("動態調用 Add 函數,result: ", result[0].Int())
}

注意:雖然反射可以為我們提供一些便利的操作,但是代碼的可讀性和可維護性會降低,且會降低性能,需要在實際生產中謹慎使用。

user avatar soroqer 頭像 huaihuaidehongdou 頭像 tongbo 頭像 kohler21 頭像 shumile_5f6954c414184 頭像 buildyuan 頭像 kubeexplorer 頭像 yian 頭像 tssc 頭像 yuzhoustayhungry 頭像 dalideshoushudao 頭像 wnhyang 頭像
點贊 80 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.