写点什么

Golang 基础笔记十六之反射

作者:Hunter熊
  • 2025-07-30
    北京
  • 本文字数:1269 字

    阅读完需:约 4 分钟

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())}
复制代码


注意:虽然反射可以为我们提供一些便利的操作,但是代码的可读性和可维护性会降低,且会降低性能,需要在实际生产中谨慎使用。

发布于: 刚刚阅读数: 2
用户头像

Hunter熊

关注

公众号:Hunter后端 2018-09-17 加入

Python后端工程师,欢迎互相沟通交流

评论

发布
暂无评论
Golang基础笔记十六之反射_golang_Hunter熊_InfoQ写作社区