Go的反射

本文介绍了Go语言中的反射机制,包括如何通过反射获取变量的类型信息和值信息。重点讨论了如何利用reflect包的TypeOf()和ValueOf()函数,以及如何访问结构体字段和方法。同时提到了类型(Type)与种类(Kind)的区别,并强调了反射在修改变量值时的注意事项,如不可寻址的变量和非导出成员无法访问。
摘要由CSDN通过智能技术生成

反射:

反射是指在程序运行期对程序本身进行访问和修改的能力,即可以在运行时动态获取变量的各种信息。
Go的反射是通过接口的类型信息实现的,即反射建立在接口类型的基础上:当向接口变量赋予一个实体类型的时候,接口会存储实体的类型信息(Type)和值信息(Value)。因此我们可以在运行时利用反射:

  • 可以获取变量的类型信息(Type)比如:比如变量的类型信息比如:(type)以及类别(kind),如果是结构体变量,还可以获取到结构体本身的信息(字段与方法)
  • 还可以用于获取变量的值信息或者实例信息Value(当变量是一个ptr时)
  • 通过反射,还可以修改变量的值,可以调用关联的方法(跟Java中的反射定义基本一样)。

【Tips】:Type是一个定义在reflect包中的interface,而Value是定义在reflect包中的一个struct,Value其实现了Type接口

Go中反射相关的包是reflect,reflect 提供了2个重要函数:

  • ValueOf():获取变量的值信息,即pair中的 value
  • TypeOf():获取变量的类型信息,即pair中的 concrete type

通过反射获取(接口)变量的类型信息

此时要通过reflect的Type及其相关操作来实现:Type相关主要用于获取一个(接口)变量的类型信息,而不是实例信息(实例信息通过Value来获取)!!!

注意点:

  • 如果想访问结构体类型的字段只能通过获取结构体类型变量的基础类型Type这种方式来获取其字段信息,此时如果变量不是指针类型,则可以通过reflect.TypeOf()来获取其concrete type,concrete type即为其基础类型;如果变量是指针类型,则必须还得通过Type.Elem()来获取其基础类型(基础类型也叫基类型)
  • 利用反射同样可以访问那些非导出成员
  • 利用反射同样可以访问结构体类型的tag信息
  • 在获取结构体类型变量对应的结构体类型的方法成员时,要记得区分开指针类型和基础类型,如果方法被声明为func (typ * Type) func1(){…}则,需要通过该变量的指针类型Type来访问对应的方法成员(此时还可以访问那些被声明为基础类型所用拥有的方法也就是func (typ Type) func2(){…}这样的方法),如果方法被声明为func (typ Type) func2(){…},则只能通过该变量的基础类型Type来访问对应的方法成员

这里注意一下类型(Type)与种类(Kind)的区别:

  • Type是原生数据类型: int、string、bool、float32 ,以及 type 定义的类型,对应的反射获取方法是reflect.Type 中 的 Name(),

  • Kind是对象归属的品种:Int、Bool、Float32、Chan、String、Struct、Ptr(指针)、Map、Interface、Fune、Array、Slice、Unsafe
    Pointer等

比如:
type Person struct{...}
这里 Person 即为 type
    struct 即为其kind
package test
/*
@Author:David Ma
@Date:2020-12-07
@Content:reflect_demo
*/
import (
	"../demo"
	"fmt"
	"reflect"
	"testing"
)

func TestReflect(t *testing.T)  {
	u := new(demo.User)
	u.SetPhone("12345678901")
	u.SetUser
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Go 语言中,反射是一种机制,可以在程序运行时动态获取变量的类型信息和值信息,并可以对其进行修改。反射可以使代码更加灵活,但也会带来一定的性能损失。 Go 语言中的反射主要通过 `reflect` 包来实现。`reflect` 包提供了两个重要的类型:`Type` 和 `Value`,分别表示类型信息和值信息。通过 `Type` 和 `Value`,我们可以获取变量的类型信息和值信息,并可以对其进行修改。 下面是一个使用反射获取变量类型和值的示例代码: ```go package main import ( "fmt" "reflect" ) func main() { var x float64 = 3.14 fmt.Println("type:", reflect.TypeOf(x)) fmt.Println("value:", reflect.ValueOf(x)) } ``` 在上面的示例代码中,我们定义了一个 `float64` 类型的变量 `x`,然后使用 `reflect.TypeOf()` 和 `reflect.ValueOf()` 函数分别获取变量的类型信息和值信息,并打印出来。由于 `reflect.TypeOf(x)` 返回的是一个 `reflect.Type` 类型的值,因此我们需要使用 `fmt.Println()` 函数来打印其名称。而 `reflect.ValueOf(x)` 返回的是一个 `reflect.Value` 类型的值,因此我们可以直接使用 `%v` 格式化符号来打印其值。 除了获取变量的类型信息和值信息之外,反射还可以用于动态调用函数和修改变量的值。例如,通过 `Value` 类型的 `Elem()` 方法可以获取指向变量的指针,并使用 `Set()` 方法来修改变量的值。 下面是一个使用反射动态修改变量值的示例代码: ```go package main import ( "fmt" "reflect" ) func main() { var x float64 = 3.14 v := reflect.ValueOf(&x).Elem() v.SetFloat(6.28) fmt.Println(x) } ``` 在上面的示例代码中,我们首先定义了一个 `float64` 类型的变量 `x`,然后使用 `reflect.ValueOf(&x).Elem()` 获取指向变量的指针,并使用 `SetFloat()` 方法将其值修改为 `6.28`。最后,我们打印出变量 `x` 的值,可以看到其值已经被修改为 `6.28`。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值