Golang 全面展示反射技术使用 (一)

package main

import (
    "fmt"
    "reflect"
)

//父对象
type Human struct {
    name string //私有字段
    //Age是公有字段定义方式(反射可修改它的值),age是私有字段定义方式(反射不可修改它的值)
    Age   int    //公有字段
    phone string //私有字段
}

//子对象,因为有了匿名字段,所以就继承了父对象Human的所有字段,还有父对象已经实现了的方法
type Student struct {
    Human         //匿名字段
    school string //私有字段
    //Loan是公有字段定义方式(反射可修改它的值),loan是私有字段定义方式(反射不可修改它的值)
    Loan float32 //借款
}

//子对象,因为有了匿名字段,所以就继承了父对象Human的所有字段,还有父对象已经实现了的方法
type Employee struct {
    Human          //匿名字段
    company string //私有字段
    //Money是公有字段定义方式(反射可修改它的值),money是私有字段定义方式(反射不可修改它的值)
    Money float32 //花钱
}

//在多个对象共有的匿名字段Human上面定义了一个方法,这个方法就是一个继承方法
func (h *Human) SayHi() (hi string) {
    hi = h.name + " Said: Hi, I am " + h.name + " you can call me on " + h.phone
    return hi
}

//Employee的method重写继承Human的method
func (e *Employee) SayHi() (hi string) {
    hi = e.name + " Said: Hi, I am " + e.name + " I work at " + e.company + ". Call me on " + e.phone
    return hi
}

//给两个子对象Student和Employee添加一个继承方法,只需要在父对象Human上实现该方法即可
func (h *Human) Sing(song string) (out string) {
    out = h.name + " is singing the song - " + song //谁在唱歌
    return out
}

//给两个子对象Student和Employee添加一个继承方法,只需要在父对象Human上实现该方法即可
func (h *Human) Guzzle(beer string) (out string) {
    out = h.name + " is guzzling his/her beer - " + beer //谁在狂饮啤酒
    return out
}

//Student实现BorrowMoney方法
func (s *Student) BorrowMoney(amount float32) (out float32) {
    s.Loan += amount //累加借款的金额
    out = s.Loan
    return out
}

//Employee实现SpendSalary方法
func (e *Employee) SpendSalary(amount float32) (out float32) {
    e.Money -= amount //累减剩余的薪水
    out = e.Money
    return out
}

//以下3个接口内部的方法,返回值参数的名称及其类型必须显式地声明

// 定义男子汉接口
type Men interface {
    SayHi() (hi string)
    Sing(song string) (out string)
    Guzzle(beer string) (out string)
}

//定义小伙子接口
type YoungChap interface {
    SayHi() (hi string)
    Sing(song string) (out string)
    BorrowMoney(amount float32) (out float32)
}

//定义老先生接口
type ElderlyGent interface {
    SayHi() (hi string)
    Sing(song string) (out string)
    SpendSalary(amount float32) (out float32)
}

//Go语言的反射技术范例
func main() {
    mm := make(map[int]string, 5)
    mm[1] = "aaaa"
    mm[2] = "bbbb"
    mm[3] = "cccc"
    mm[4] = "dddd"
    mm[5] = "eeee"
    mm[6] = "ffff"
    fmt.Println(len(mm)) // cap(mm) cap是不能计算机map的容量

    m := make([]map[int]chan string, 5, 10)
    fmt.Println(len(m), cap(m)) // 5 10
    x := 3.69
    y := 0.01
    z1 := x + y
    fmt.Printf("%v\n", z1) // output: 3.6999999999999997
    z2 := (x + y) * 100 / 100
    fmt.Printf("%0.2f\n", z2) // output: 3.70

    mike := Student{Human{"Mike", 25, "222-222-XXX"}, "MIT", 0.00}          //小伙子
    jack := Student{Human{"Jack", 21, "222-222-4579"}, "Tsinghua", 1500.00} //小伙子
    tom := Student{Human{"Tom", 29, "222-222-4548"}, "Peking", 3200.00}     //男子汉
    paul := Student{Human{"Paul", 26, "111-222-1314"}, "Harvard", 100}      //小伙子
    tim := Employee{Human{"Tim", 35, "222-222-9948"}, "Sina", 7500.00}      //男子汉
    kite := Employee{Human{"Kite", 36, "222-222-7848"}, "Sohu", 10500.00}   //男子汉
    sam := Employee{Human{"Sam", 58, "444-222-5520"}, "Golang Inc.", 8000}  //老先生

    //定义Men切片
    slMen := make([]Men, 3)
    //这三个对象有2种不同类型的元素(学生和职员)
    //所有元素都能存储到YoungChap、Men和ElderlyGent接口里,因为它们本质上都是interface的别名
    slMen[0], slMen[1], slMen[2] = &paul, &sam, &mike //注意:这样赋值超过3个会越界
    //使用 append 追加动态扩容切片的大小,让超过3个的对象也可以存储到接口的切片里
    slMen = append(slMen, &jack, &tom, &kite) //append方法会分配新的内存空间存储无法装进来的数据

    fmt.Println("------------------- 反射 -------------------")
    p1 := reflect.ValueOf(&tom)
    p1 = reflect.Indirect(p1) //此行代码等价于 p1 = p1.Elem()
    v1 := p1.FieldByName("Loan")
    if v1.Kind() == reflect.Float32 {
        if v1.CanSet() {
            v1.SetFloat(3650.88)
        }
    }
    fmt.Println("reflect.ValueOf(&tom) is ", p1)
    fmt.Println("p1 = reflect.Indirect(p1) is ", p1)
    fmt.Println(`v1 := p1.FieldByName("Loan") is `, v1)
    fmt.Println("tom is ", tom)
    fmt.Println("------------------- 反射 -------------------")

    p2 := reflect.ValueOf(&tim)
    v2 := p2.Elem()
    //直接出现panic,问题出在money字段首字母小写定义的是私有字段,反射无法修改
    v2.Field(2).SetFloat(3650.88)

    fmt.Println("reflect.ValueOf(&tim) is ", p2)
    fmt.Println("p2.Elem() is ", p2.Elem())
    fmt.Println("v2 := p2.Elem() is ", v2)
    fmt.Println("tim is ", tim)

    v2.Field(0).FieldByName("Age").SetInt(37) //修改父对象Human里的公有字段Age的值
    fmt.Println("tim is ", tim)
    fmt.Println("--------------------------- 反射 ----------------------------------------")

    var input1 float32 = 1300.25 // 等价于 input1 := float32(1300.25)
    m1 := reflect.ValueOf(&jack).MethodByName("BorrowMoney")
    output1 := m1.Call([]reflect.Value{reflect.ValueOf(input1)})
    fmt.Println(output1)
    fmt.Println(output1[0])

    m2 := reflect.ValueOf(&jack).MethodByName("SayHi")
    output2 := m2.Call([]reflect.Value{})
    fmt.Println(output2)
    fmt.Println(output2[0])
    fmt.Println("--------------------------- 反射 ----------------------------------------")

    //定义男子汉Men接口类型的变量inMen
    var inMen Men
    //Men能存储Employee
    //因为实现男子汉接口内部的方法时,这些方法的接收参数使用了指针,所以给接口切片赋值时必须使用对象的地址赋值
    inMen = &tim
    hi4 := inMen.SayHi()
    out3 := inMen.Sing("Born to be wild")
    out4 := inMen.Guzzle("Budweiser")
    fmt.Println(hi4)
    fmt.Println(out3)
    fmt.Println(out4)
    fmt.Println("--------------------------------------")

    obj := reflect.ValueOf(&tim)
    element := obj.Elem()
    typeOfElem := element.Type()
    fmt.Println(typeOfElem, obj.Type())
    fmt.Println(typeOfElem.Field(0))
    fmt.Println("output: ", element.Field(0).Interface())                             //output: {Tim 37 222-222-9948}
    fmt.Println("output: ", element.Field(0).Interface().(Human).name)                //output: Tim
    fmt.Println("output: ", element.Field(0).Interface().(Human).Age)                 //output: 37
    fmt.Println("output: ", reflect.TypeOf(element.Field(0).Interface().(Human).Age)) //output: int
    fmt.Println("output: ", element.Field(0).Interface().(Human))                     //output:  {Tim 37 222-222-9948}
    fmt.Println("output: ", element.FieldByName("Human"))                             //output:  {Tim 37 222-222-9948}
    fmt.Println("output: ", element.FieldByName("Human").Type())                      //output: main.Human
    for i := 0; i < element.NumField(); i++ {
        fmt.Println("typeOfElem.Field(", i, ").Name :", typeOfElem.Field(i).Name, "element.Field(", i, ").Type() :", element.Field(i).Type(), "element.Field(", i, ") :", element.Field(i))
        if typeOfElem.Field(i).Name == "Human" {
            for j := 0; j < element.Field(i).NumField(); j++ {
                fmt.Println(element.FieldByName("Human").Type().Field(j).Name, element.Field(i).Field(j).Type(), element.Field(i).Field(j))
                // v.Kind() == reflect.Float64 // 判断字段的类型
            }
        }
    }

    fmt.Println("----------------- 反射调用切片接口类型的对象 ---------------------")
    fmt.Println(slMen[0])
    fmt.Println(reflect.ValueOf(slMen[0]))
    inMen2 := reflect.ValueOf(slMen[0])
    element2 := inMen2.Elem()
    typeOfElem2 := element2.Type()
    fmt.Println(typeOfElem2, inMen2.Type())
    fmt.Println(typeOfElem2.Field(0))
    fmt.Println("output: ", element2.Field(0).Interface())                             //output: {Paul 26 111-222-1314}
    fmt.Println("output: ", element2.Field(0).Interface().(Human).name)                //output: Paul
    fmt.Println("output: ", element2.Field(0).Interface().(Human).Age)                 //output: 26
    fmt.Println("output: ", reflect.TypeOf(element2.Field(0).Interface().(Human).Age)) //output: int
    fmt.Println("output: ", element2.Field(0).Interface().(Human))                     //output:  {Paul 26 111-222-1314}
    fmt.Println("output: ", element2.FieldByName("Human"))                             //output:  {Paul 26 111-222-1314}
    fmt.Println("output: ", element2.FieldByName("Human").Type())                      //output: main.Human

    var input12 = "Snow Bear" // 等价于 input12 := "Snow Bear"
    m12 := reflect.ValueOf(slMen[0]).MethodByName("Guzzle")
    output12 := m12.Call([]reflect.Value{reflect.ValueOf(input12)})
    fmt.Println(output12)
    fmt.Println(output12[0])
    fmt.Println("inMen2 :", inMen2, "inMen2.Type() :", inMen2.Type())
    /* output : inMen2 : &{{Paul 26 111-222-1314} Harvard 100} inMen2.Type() : *main.Student */
    //输出所有方法
    for i := 0; i < inMen2.NumMethod(); i++ {
        fmt.Println(inMen2.Type().Method(i).Name, inMen2.Type().Method(i).Type)
        /*
            output :
            BorrowMoney func(*main.Student, float32) float32
            Guzzle func(*main.Student, string) string
            SayHi func(*main.Student) string
            Sing func(*main.Student, string) string
        */
    }

}




控制台输出:

2017/06/17 15:22:13 server.go:73: Using API v1
2017/06/17 15:22:13 debugger.go:97: launching process with args: [/root/code/go/src/contoso.org/hello/debug]
API server listening at: 127.0.0.1:2345
2017/06/17 15:22:14 debugger.go:505: continuing
6
5 10
3.6999999999999997
3.70
------------------- 反射 -------------------
reflect.ValueOf(&tom) is  {{Tom 29 222-222-4548} Peking 3650.88}
p1 = reflect.Indirect(p1) is  {{Tom 29 222-222-4548} Peking 3650.88}
v1 := p1.FieldByName("Loan") is  3650.88
tom is  {{Tom 29 222-222-4548} Peking 3650.88}
------------------- 反射 -------------------
reflect.ValueOf(&tim) is  &{{Tim 35 222-222-9948} Sina 3650.88}
p2.Elem() is  {{Tim 35 222-222-9948} Sina 3650.88}
v2 := p2.Elem() is  {{Tim 35 222-222-9948} Sina 3650.88}
tim is  {{Tim 35 222-222-9948} Sina 3650.88}
tim is  {{Tim 37 222-222-9948} Sina 3650.88}
--------------------------- 反射 ----------------------------------------
[<float32 Value>]
2800.25
[Jack Said: Hi, I am Jack you can call me on 222-222-4579]
Jack Said: Hi, I am Jack you can call me on 222-222-4579
--------------------------- 反射 ----------------------------------------
Tim Said: Hi, I am Tim I work at Sina. Call me on 222-222-9948
Tim is singing the song - Born to be wild
Tim is guzzling his/her beer - Budweiser
--------------------------------------
main.Employee *main.Employee
{Human  main.Human  0 [0] true}
output:  {Tim 37 222-222-9948}
output:  Tim
output:  37
output:  int
output:  {Tim 37 222-222-9948}
output:  {Tim 37 222-222-9948}
output:  main.Human
typeOfElem.Field( 0 ).Name : Human element.Field( 0 ).Type() : main.Human element.Field( 0 ) : {Tim 37 222-222-9948}
name string Tim

Age int 37
phone string 222-222-9948
typeOfElem.Field( 1 ).Name : company element.Field( 1 ).Type() : string element.Field( 1 ) : Sina
typeOfElem.Field( 2 ).Name : Money element.Field( 2 ).Type() : float32 element.Field( 2 ) : 3650.88
----------------- 反射调用接口类型的对象 ---------------------
&{{Paul 26 111-222-1314} Harvard 100}
&{{Paul 26 111-222-1314} Harvard 100}
main.Student *main.Student
{Human  main.Human  0 [0] true}
output:  {Paul 26 111-222-1314}
output:  Paul
output:  26
output:  int
output:  {Paul 26 111-222-1314}
output:  {Paul 26 111-222-1314}
output:  main.Human
[Paul is guzzling his/her beer - Snow Bear]
Paul is guzzling his/her beer - Snow Bear
inMen2 : &{{Paul 26 111-222-1314} Harvard 100} inMen2.Type() : *main.Student
BorrowMoney func(*main.Student, float32) float32
Guzzle func(*main.Student, string) string
SayHi func(*main.Student) string
Sing func(*main.Student, string) string


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值