Go语言反射(reflect)

反射是应用程序检查其所拥有的结构,尤其是类型的一种能。每种语言的反射模型都不同,并且有些语言根本不支持反射。Go语言实现了反射,反射机制就是在运行时动态调用对象的方法和属性,即可从运行时态的示例对象反求其编码阶段的定义,标准库中reflect包提供了相关的功能。在reflect包中,通过reflect.TypeOf(),reflect.ValueOf()分别从类型、值的角度来描述一个Go对象。

func TypeOf(i interface{
   
   }) Type
type Type interface 

func ValueOf(i interface{
   
   }) Value
type Value struct 

在Go语言的实现中,一个interface类型的变量存储了2个信息, 一个<值,类型>对,<value,type> :

(value, type)

value是实际变量值,type是实际变量的类型。两个简单的函数,reflect.TypeOf 和 reflect.ValueOf,返回被检查对象的类型和值。

例如,x 被定义为:var x float64 = 3.4,那么 reflect.TypeOf(x) 返回 float64,reflect.ValueOf(x) 返回 3.4。实际上,反射是通过检查一个接口的值,变量首先被转换成空接口。这从下面两个函数签名能够很明显的看出来:

func TypeOf(i interface{
   
   }) Type
func ValueOf(i interface{
   
   }) Value

reflect.Type 和 reflect.Value 都有许多方法用于检查和操作它们。

Type主要有:
Kind() 将返回一个常量,表示具体类型的底层类型
Elem()方法返回指针、数组、切片、字典、通道的基类型,这个方法要慎用,如果用在其他类型上面会出现panic

Value主要有:
Type() 将返回具体类型所对应的 reflect.Type(静态类型)
Kind() 将返回一个常量,表示具体类型的底层类型

反射可以在运行时检查类型和变量,例如它的大小、方法和 动态 的调用这些方法。这对于没有源代码的包尤其有用。

由于反射是一个强大的工具,但反射对性能有一定的影响,除非有必要,否则应当避免使用或小心使用。下面代码针对int、数组以及结构体分别使用反射机制,其中的差异请看注释。

package main

import (
    "fmt"
    "reflect"
)

type Student struct {
   
   
    name string
}

func main() {
   
   

    var a int = 50
    v := reflect.ValueOf(a) // 返回Value类型对象,值为50
    t := reflect.TypeOf(a)  // 返回Type类型对象,值为int
    fmt.Println(v, t, v.Type(), t.Kind())

    var b [5]int = [5]int{
   
   5, 6, 7, 8}
    fmt.Println(reflect.TypeOf(b), reflect.TypeOf(b).Kind(),reflect.TypeOf(b).Elem()) // [5]int array int

    var Pupil Student
    p := reflect.ValueOf(Pupil) // 使用ValueOf()获取到结构体的Value对象

    fmt.Println(p.Type()) // 输出:Student
    fmt.Println(p.Kind()) // 输出:struct

}

在Go语言中,类型包括 static type和concrete type. 简单说 static type是你在编码是看见的类型(如int、string),concrete type是实际具体的类型,runtime系统看见的类型。

Type()返回的是静态类型,而kind()返回的是具体类型。上面代码中,在int,数组以及结构体三种类型情况中,可以看到kind(),type()返回值的差异。

通过反射可以修改原对象

d.CanAddr()方法:判断它是否可被取地址
d.CanSet()方法:判断它是否可被取地址并可被修改

通过一个settable的Value反射对象来访问、修改其对应的变量值:

package main

import (
    "fmt"
    "reflect"
)

type Student struct {
   
   
    name string
    Age  int
}

func main() {
   
   

    var a int = 50
    v := reflect.ValueOf(a) // 返回Value类型对象,值为50
    t := reflect.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值