本文章主要讲解一下reflect包中TypeOf和ValueOf两个函数的工作原理。
TypeOf
在 Go语言中通过调用 reflect.TypeOf 函数,我们可以从一个任何接口类型的值创建一个 reflect.Type 值。reflect.Type 值表示着此接口值的类型。通过此值,我们可以得到很多此接口类型的信息。当然,我们也可以将一个接口值传递给一个 reflect.TypeOf 函数调用,但是此调用将返回一个表示着此接口值的动态类型的 reflect.Type 值。
实际上,reflect.TypeOf 函数的唯一参数的类型为 interface{},reflect.TypeOf 函数将总是返回一个表示着此唯一接口参数值的动态类型的 reflect.Type 值。
TypeOf 的源码如下
type eface struct{
_type *_type
data unsafe.Pointer
}
type emptyInterface struct{
typ *rtype
word unsafe.Pointer
}
func TypeOf (i interface()) Type{
eface := *(* emptyInterface)(unsafe.Pointer(&i)) //&i 是eface 类型
return toType(eface.typ)
}
这里是反射的一些简单应用
package main
import "fmt"
import "reflect"
type Eggo struct{
name string
}
func (e Eggo) A(){
fmt.Println(e.name)
}
func main() {
a := Eggo{name:"eggo"}
t:=reflect.TypeOf(a)
fmt.Println(t.NumMethod(),t.Kind(),t)
}
输出如下:1 struct main.Eggo。t.Kind()会返回golang原始类型,原始类型string,struct等等
package main
import "fmt"
import "reflect"
import "encoding/json"
type Stu struct {
Name string `json:"name"`
Age int
HIgh bool
sex string
Class *Class `json:"class"`
}
type Class struct {
Name string
Grade int
}
type Eggo struct{
Name string
}
func (e Eggo) A(){
fmt.Println(e.Name)
}
func main() {
/*
stu := Stu{
Name: "张三",
Age: 18,
HIgh: true,
sex: "男",
}
//指针变量
cla := new(Class)
cla.Name = "1班"
cla.Grade = 3
stu.Class=cla
//Marshal失败时err!=nil
jsonStu, err := json.Marshal(stu)
if err != nil {
fmt.Println("生成json字符串错误")
}
//jsonStu是[]byte类型,转化成string类型便于查看
fmt.Println(string(jsonStu))*/
a := Eggo{Name:"eggo"}
b := &Eggo{}
bdata, err:= json.Marshal(a)
if err != nil {
fmt.Println("生成json字符串错误")
}
t:=reflect.TypeOf(a)
fmt.Println(string(bdata))
aa := reflect.New(t).Interface()
fmt.Println("...........",t,aa,b)
json.Unmarshal(bdata, aa)
fmt.Println("reflect-get-name",(aa).(*Eggo).Name)
}
输出如下:
{"Name":"eggo"}
........... main.Eggo &{} &{}
reflect-get-name eggo。
根据反射解析json。cellnet使用的就是这种方式编码和解码