Golang的反射
反射是指,在程序运行的时候,可以动态的检查自身的类型,结构和其他信息。
要了解Go语言的反射,我们需要了解两个概念。
reflect.Type
reflect.Value
我们想要在运行时知道类型和值,怎么办呢?很明显就是编译器帮我们把这些信息存下来在程序的某个地方。 Type就是类型,Value就是值。reflect包里有几个重要的函数,需要了解一下:
reflect.TypeOf
获取所传入值的类型,返回的是reflect.Type
。而Type又分为很多种Kind,Kind有这么几种取值:const ( Invalid Kind = iota Bool Int Int8 Int16 Int32 Int64 Uint Uint8 Uint16 Uint32 Uint64 Uintptr Float32 Float64 Complex64 Complex128 Array Chan Func Interface Map Ptr Slice String Struct UnsafePointer )
有点晕是不是?多看几遍就不晕了。
reflect.ValueOf
返回所传入值的值,但是类型是reflect.Value
。根据reflect.Value
可以拿到它的 Type,使用Type()
:package main import ( "fmt" "reflect" ) func main() { v := reflect.ValueOf(3) fmt.Printf("TypeOf: %s\n", v.Type()) }
Value.CanSet
返回这个Value是不是能被更新值。设想,如果我们想从环境变量里,把环境变量里设置的值刷到一个结构体里,就需要 用到这个函数了。注意,只有变量才能被更新,什么是变量呢?就是,我们可以拿到它在内存中的地址,我们就可以更改值的意思。看看下面的例子:x := 2 // 2 是常量,x是变量,x存的值是2。x是可以被更新的。 a := reflect.ValueOf(2) // a 不是变量,因为a代表的值是2,是一个常量。 b := reflect.ValueOf(x) // b 不是变量,因为b代表的值是x包含的值,也是2,是一个常量。 c := reflect.ValueOf(&x) // c 不是变量,因为c代表的值是x的地址,例如0x11223344,也是一个常量。 d := c.Elem() // d是变量,因为c是x的地址的值,c.Elem() 是x地址所指向的那个值,我们知道了x的地址,自然就可以更新x了。
有点难理解对不对?难就对了,因为这个要对内存有一定的了解,如果实在看不懂,就还是去看看基础的书吧。我目前一句两句话也解释不清楚。 如果想理解的话,推荐:
- 《深入理解计算机系统》
- 《编程范式》
- https://blog.golang.org/laws-of-reflection
- 《The Go Programming Language》
- https://golang.org/pkg/reflect
更多文章
本站热门
- socks5 协议详解
- zerotier简明教程
- 搞定面试中的系统设计题
- frp 源码阅读与分析(一):流程和概念
- 用peewee代替SQLAlchemy
- Golang(Go语言)中实现典型的fork调用
- DNSCrypt简明教程
- 一个Gunicorn worker数量引发的血案
- Golang validator使用教程
- Docker组件介绍(二):shim, docker-init和docker-proxy
- Docker组件介绍(一):runc和containerd
- 使用Go语言实现一个异步任务框架
- 协程(coroutine)简介 - 什么是协程?
- SQLAlchemy简明教程
- Go Module 简明教程