博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
go语言reflect实验
阅读量:5326 次
发布时间:2019-06-14

本文共 4943 字,大约阅读时间需要 16 分钟。

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

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).

转载于:https://www.cnblogs.com/feixiangsnail15-12-28/p/9177988.html

你可能感兴趣的文章
面向对象的优点
查看>>
套接口和I/O通信
查看>>
阿里巴巴面试之利用两个int值实现读写锁
查看>>
浅谈性能测试
查看>>
Winform 菜单和工具栏控件
查看>>
CDH版本大数据集群下搭建的Hue详细启动步骤(图文详解)
查看>>
巧用Win+R
查看>>
浅析原生js模仿addclass和removeclass
查看>>
Python中的greenlet包实现并发编程的入门教程
查看>>
java中遍历属性字段及值(常见方法)
查看>>
深入理解jQuery框架-框架结构
查看>>
YUI3自动加载树实现
查看>>
python知识思维导图
查看>>
当心JavaScript奇葩的逗号表达式
查看>>
App Store最新审核指南(2015年3月更新版)
查看>>
织梦MIP文章内容页图片适配百度MIP规范
查看>>
点击复制插件clipboard.js
查看>>
[Kali_BT]通过低版本SerialPort蓝牙渗透功能手机
查看>>
C语言学习总结(三) 复杂类型
查看>>
HNOI2018
查看>>