//反射的本质就是根据传入的结构体的类型不同从而生成不同的结构体对象,然后通过查找原结构体的方法,来动态调用其方法。

package main

import (
"fmt"
"reflect"
)

var log = fmt.Println

func main() {

reflect1()
// reflect2()
//reflect3()
//reflect4()
//reflect5()
}

type T5 struct {
Name string
}

func reflect5() {
var i int = 1
v5 := reflect.ValueOf(&i)
v5 = reflect.Indirect(v5) //等同于Elem()
//v5 = v5.Elem()
v5v := v5.Interface()
if v5.Kind() == reflect.Int {
log(v5.Kind(), "kind")
v5.SetInt(2) //传地址才可以设置
}
v5i := v5.Interface()
log(v5v, v5i, "v5v")
s := T5{"x"}
value5 := reflect.ValueOf(&s).Elem()
log(value5.Interface())
f0 := value5.FieldByName("Name")
log(f0, "f0")
if f0.Kind() == reflect.String {
if f0.CanSet() {
f0.SetString("y")
log(f0, s, value5, "fsv")
}
}
}

type User struct {
Name string
Age int
}

func (u User) showUser() {
log("showuser")
}
func (u User) showAge() {
log("showAge")
}
func reflect4() {
u := &User{"maliu", 20}
t := reflect.TypeOf(u)
v := reflect.ValueOf(u)
vt := v.Type() //根据reflect.value还原类型
tk := t.Kind() //还原其底层基础类型
isCan := v.CanSet()
log(t, v, vt, tk, isCan, "tv")
u2 := v.Interface()
u1 := v.Interface().(*User) //将reflect.Value类型还原为原始类型
log(u, u1, u2, "u1")
u3 := (*User)(nil) //将nil强转为User的指针类型
log(u3, "u3")
t4 := reflect.TypeOf(u3).Elem()
log(t4.Name(), t4, "t4")
m4 := map[string]reflect.Type{}
m4[t4.Name()] = t4
log(m4, "m4")
elem4, ok4 := m4["User"]
log(elem4, ok4)
r4 := reflect.New(elem4).Elem() //New出来的是指针类型
r5 := r4.Interface() // 该方法会返回一个value的值,不过类型是interface
r6 := r5.(User) //创建一个原始类型的空值

r6.Name = "hi,I am r6"
log(r4, r5, r6, "r4")
t2 := t.Elem()
for i := 0; i < t2.NumField(); i++ {
log(t2.Field(i).Name, "field")
}
for i := 0; i < t2.NumMethod(); i++ {
log(t2.Method(i).Name, "Method")
}

}

//-------------------------
type test3 struct {
Name string
}

func reflect3() {
var temp3 interface{} = test3{Name: "wangwu"}
t3 := reflect.TypeOf(temp3).Elem()
log(t3, "t3") //会报错
}

//--------------
type test2 struct {
Name string
Sex int
}

type tmpStruct struct {
Name string
}
type tink interface {
ShowName()
ShowName2()
}

func (c tmpStruct) ShowName() {
log(c.Name, "c.Name")
}
func (c *tmpStruct) ShowName2() {
log(c.Name, "c.Name2")
}
func reflect2() {
m := map[string]int{"a": 1, "b": 2}
elem, ok := m["a"] //存在就是true
log(m, "m")
log(elem, ok, "elementok")
var emp tink = &tmpStruct{Name: "lisi"} //如果接口有任意一个方法的调用者是指针,那么接口只能被指针赋值
c := reflect.TypeOf(emp).Elem()

temp := reflect.New(c).Elem().Interface() //new的参数必须是结构体typeof实例返回的内容也就是reflect.type类型,直接传结构体没用
log(c, temp, "temp")
}

//------------------------
type ControllerInterface interface {
Init(action string, method string)
}
type Controller struct {
Action string
Method string
Tag string `json:"tag"`
}

func (c *Controller) Init(action string, method string) {
c.Action = action
c.Method = method
log("I am in init")
}
func (c *Controller) Test() {
log("I am Test func")
}
func reflect1() {
runController := &Controller{
Action: "Run1",
Method: "Get",
}

var i ControllerInterface
i = runController
v := reflect.ValueOf(i) //i接口的值
log("value", v)
t := reflect.TypeOf(i) //i接口类型
log("Type", t)
controllerValue := v.Elem() //解掉指针之后的值
log(controllerValue, "cv")
log(controllerValue.Field(0).String()) //第一个值的字符串形式
controllerType := t.Elem()
log(controllerType, "controllerType")
log(controllerType.Name(), "typeName()")
log(controllerType.Field(0), "Field0")
log(controllerType.Field(1), "Field1")
log(controllerType.Field(2), "Field2")
fb, _ := controllerType.FieldByName("Method") //通过字段获取值信息
log(fb, "FieldByName")
tag := controllerType.Field(2).Tag //Field(第几个字段,index从0开始)
log("tag", tag, tag.Get("json")) //获取别名
method, _ := t.MethodByName("Init")
log(method, "method")
vMethod := v.MethodByName("Init")
log(vMethod, "vMethod")
arg1 := []reflect.Value{reflect.ValueOf("Run2"), reflect.ValueOf("POST")}
vMethod.Call(arg1)
log(i, "I am I")
arg2 := make([]reflect.Value, 0)
log(arg2, "arg2")
v.MethodByName("Test").Call(arg2)
}

//v := reflect.ValueOf(i) //i接口的值 这个类型是reflect.Type
// t := reflect.TypeOf(i) //i接口类型
// controllerValue := v.Elem() //解掉指针之后的值,这个类型是reflect.Value,非指针类型没有Elem这个方法
// controllerValue.Field(0).String() //第一个字段的字符串形式
// controllerType := t.Elem()//解掉指针之后的类型 这个类型是reflect.Type,非指针类型没有Elem这个方法
//controllerType.Name()//去掉包名之后的类型名
//controllerType.Field(1)//返回一个结构体包含字段名,类型,第几个字节,第几个元素,bool值
// tag := controllerType.Field(2).Tag //Field(第几个字段,index从0开始)
//vMethod := v.MethodByName("Init") //地址值,可以通过Call并传入切片调用,可以改变原值
//reflect.Value //是一种反射值类型
//method, _ := t.MethodByName("Init")

//go 语言没有提供根据类型名称返回类型变量的功能,但是你可以通过设置一个:
// var typemap = make(map[string]reflect.Type)
// 然后把你的结构体注册到这个表中,之后你可以通过这个表通过类型名获取类型,之后用反射创建对象就行了。
//感觉应该是用reflect来解决, 但是reflect动态生成,得知道类型,reflect.Type. reflect.New(type)可以动态生成一个reflect.Value。 得到value了就可以用接口来转换了

// func New(typ Type) Value New returns a Value representing a pointer to a new zero value for the specified type. That is, the returned Value's Type is PtrTo(typ).

posted on 2018-06-13 15:18  feixiangsnail  阅读(219)  评论(0编辑  收藏  举报