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("%vn",z1) // output: 3.6999999999999997 z2 := (x + y) * 100 / 100 fmt.Printf("%0.2fn",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(",").Type() :",element.Field(i).Type(),") :",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 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 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |