【转】Golang Reflect反射的使用详解1 --- makeFunc的使用
转,原文: https://studygolang.com/articles/12300
----------------------------------
What you are wasting today is tomorrow for those who died yesterday; what you hate now is the future you can not go back.
你所浪费的今天是昨天死去的人奢望的明天; 你所厌恶的现在是未来的你回不去的曾经。
Go是静态类型语言。每个变量都拥有一个静态类型,这意味着每个变量的类型在编译时都是确定的:int,float32, *AutoType, []byte, chan []int 诸如此类。
动静类型
编译时就知道变量类型的是静态类型;运行时才知道一个变量类型的叫做动态类型。
1. 静态类型
静态类型就是变量声明时的赋予的类型。比如:
type MyInt int // int 就是静态类型
type A struct{
Name string // string就是静态
}
var i *int // *int就是静态类型
2. 动态类型
动态类型:运行时给这个变量复制时,这个值的类型(如果值为nil的时候没有动态类型)。一个变量的动态类型在运行时可能改变,这主要依赖于它的赋值(前提是这个变量时接口类型)。
var A interface{} // 静态类型interface{}
A = 10 // 静态类型为interface{} 动态为int
A = "String" // 静态类型为interface{} 动态为string
var M *int
A = M // 猜猜这个呢?
来看看这个例子:
//定义一个接口
type Abc interface{
String() string
}
// 类型
type Efg struct{
data string
}
// 类型Efg实现Abc接口
func (e *Efg)String()string{
return e.data
}
// 获取一个*Efg实例
func GetEfg() *Efg{
return nil
}
// 比较
func CheckAE(a Abc) bool{
return a == nil
}
func main() {
efg := GetEfg()
b := CheckAE(efg)
fmt.Println(b)
os.Exit(1)
}
关于动静态类型就到这里,详细请自行Google,百度吧。
反射
那么什么时候下使用反射呢?
有时候你想在运行时使用变量来处理变量,这些变量使用编写程序时不存在的信息。也许你正试图将来自文件或网络请求的数据映射到变量中。也许创建一个适用于不同类型的tool。在这些情况下,你需要使用反射。反射使您能够在运行时检查类型。它还允许您在运行时检查,修改和创建变量,函数和结构。
类型
你可以使用反射来获取变量的类型: var t := reflect.Typeof(v)。返回值是一个reflect.Type类型。该值有很多定义好的方法可以使用。
Name()
返回类型的名称。 但是像切片或指针是没有类型名称的,只能返回空字符串。
Kind()
Kind有slice, map , pointer指针,struct, interface, string , Array, Function, int或其他基本类型组成。Kind和Type之前要做好区分。如果你定义一个 type Foo struct {}, 那么Kind就是struct, Type就是Foo。
*小知识点:反射变量对应的Kind方法的返回值是基类型,并不是静态类型。下面的例子中:
type MyInt int
var x MyInt = 7
v := reflect.ValueOf(x)
变量v的Kind依旧是reflect.Int,而不是MyInt这个静态类型。Type可以表示静态类型,而Kind不可以。
*注意点: 在使用refelct包时, reflect包会假定你已经知道所做的是什么,否则引发panic。 例如你调用了与当前reflect.Type 不同的类型上的方法,那么就会引发panic。
Elem()
如果你的变量是一个指针、map、slice、channel、Array。那么你可以使用reflect.Typeof(v).Elem()来确定包含的类型。
案例代码
type Foo struct {
A int `tag1:"Tag1" tag2:"Second Tag"`
B string
}
func main(){
// Struct
f := Foo{A: 10, B: "Salutations"}
// Struct类型的指针
fPtr := &f
// Map
m := map[string]int{"A": 1 , "B":2}
// channel
ch := make(chan int)
// slice
sl:= []int{1,32,34}
//string
str := "string var"
// string 指针
strPtr := &str
tMap := examiner(reflect.TypeOf(f), 0)
tMapPtr := examiner(reflect.TypeOf(fPtr), 0)
tMapM := examiner(reflect.TypeOf(m), 0)
tMapCh := examiner(reflect.TypeOf(ch), 0)
tMapSl := examiner(reflect.TypeOf(sl), 0)
tMapStr := examiner(reflect.TypeOf(str), 0)
tMapStrPtr := examiner(reflect.TypeOf(strPtr), 0)
fmt.Println("tMap :", tMap)
fmt.Println("tMapPtr: ",tMapPtr)
fmt.Println("tMapM: ",tMapM)
fmt.Println("tMapCh: ",tMapCh)
fmt.Println("tMapSl: ",tMapSl)
fmt.Println("tMapStr: ",tMapStr)
fmt.Println("tMapStrPtr: ",tMapStrPtr)
}
// 类型以及元素的类型判断
func examiner(t reflect.Type, depth int) map[int]map[string]string{
outType := make(map[int]map[string]string)
// 如果是一下类型,重新验证
switch t.Kind() {
case reflect.Array, reflect.Chan, reflect.Map, reflect.Ptr, reflect.Slice:
fmt.Println("这几种类型Name是空字符串:",t.Name(), ", Kind是:", t.Kind())