zoukankan      html  css  js  c++  java
  • go语言reflect实验

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

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

  • 相关阅读:
    Linux下semaphore的使用 进程间互斥的一个好方法
    CURL编程:什么是NonASCII平台,如何取得页面的charset
    C++中的重载(Overload), 覆盖(Override)和隐藏(Hide)
    system调用虽然用了exec,但是fd, signal这些还是会保留父进程的,be careful
    addr2line,可以根据一个地址打印出对应的代码行
    POSIX Threads Programming 阅读笔记(来自劳伦斯利物浦实验室的文章)
    [Gammu]setlocale和bindtextdomain函数的用法
    常用编码
    用PL/SQL画直方图
    窗体的关闭
  • 原文地址:https://www.cnblogs.com/feixiangsnail15-12-28/p/9177988.html
Copyright © 2011-2022 走看看