Go语言(十五) 反射
反射
变量介绍
- 变量的内在机制
- 类型信息,这部分是元信息,是预先定义好的
- 值类型,这部分是在程序运行过程中动态改变的
反射介绍
- 反射与空接口
- 空接口可以存储任何类型的变量
- 在程序运行时动态获取变量的类型信息和值信息,就叫
反射
import ( "fmt" "reflect" ) func TestType(a interface{}) { //获取类型(静态信息) t := reflect.TypeOf(a) kind := t.Kind() switch kind { case reflect.Int: fmt.Printf("a is a int\n") a = 2 case reflect.String: fmt.Printf("a is a string\n") } fmt.Printf("t=%v,kind=%v\n\n",t,kind) } func TestValue(a interface{}) { v := reflect.ValueOf(a) //kind := v.Kind() t := v.Type() switch t.Kind() { case reflect.Int: fmt.Printf("a is a int\n") v.SetInt(10000) case reflect.String: v.SetString("xxx") fmt.Printf("a is a string\n") case reflect.Ptr: t1 := v.Elem().Type() switch (t1.Kind()) { case reflect.Int: v.Elem().SetInt(100) fmt.Printf("ptn is int \n") case reflect.String: v.Elem().SetString("hello") fmt.Printf("ptn is string\n") } fmt.Printf("a=%v is a point type\n",t1) } fmt.Printf("v=%v,kind=%v\n\n",v,t) } func main() { //var a int //TestType(a) //fmt.Printf("a=%v\n",a) //var b string //TestType(b) var c int TestValue(&c) var d string TestValue(&d) fmt.Printf("c=%v, d=%v\n",c,d) }
结构体反射
type Users struct { Name string `json:"name"` Age int Sex string } //1. 获取a的类型 //2. 我要动态改变a里面存的值 //3. 如果a里面存储的是一个结构体,那可以通过反射获取结构体中的字段信息以及调用结构体里面的方法 func TestValueStruct(a interface{}) { v := reflect.ValueOf(a) t := v.Type() switch t.Kind() { case reflect.Struct: fieldNum := t.NumField() fmt.Printf("field num:%d\n", fieldNum) for i := 0; i <fieldNum; i++{ field := t.Field(i) vField := v.Field(i) fmt.Printf("field[%d] name:%s, json key:%s, val:%v\n", i, field.Name, field.Tag.Get("json"), vField.Interface()) } } } func main() { var user Users user.Name = "xxx" user.Age = 100 user.Sex = "man" TestValueStruct(user) fmt.Printf("user:%#v\n", user) }
调用结构体中的方法
type S struct { A int B string } func (s *S) Test() { fmt.Printf("this is a test\n") } func (s *S) SetA (a int) { s.A = a } func main() { s := S{23,"abc"} v := reflect.ValueOf(&s) m := v.MethodByName("Test") var args1 []reflect.Value m.Call(args1) setA := v.MethodByName("SetA") var args2 []reflect.Value args2 = append(args2,reflect.ValueOf(100)) setA.Call(args2) #修改结构体中的值 fmt.Printf("s:%#v\n",s) }
反射总结以及应用场景
总结:
- 在运行时动态的获取一个变量的类型信息(typeOf)和值信息(valueOf)
- 应用场景
- 各种数据库的ORM
- 配置文件相关的库,比如yaml,ini等
- 序列化和反序列化,比如json,protoBuf等数据协议
- 各种数据库的ORM
json序列化简版代码
package json_reflect import ( "fmt" "reflect" ) func Marshals(data interface{}) (jsonStr string) { t := reflect.TypeOf(data) v := reflect.ValueOf(data) switch t.Kind(){ case reflect.String,reflect.Int,reflect.Int32: jsonStr = fmt.Sprintf("\"%v\"", data) case reflect.Struct: numField := t.NumField() for i := 0; i < numField; i++ { //类型信息 name := t.Field(i).Name tag := t.Field(i).Tag.Get("json") if len(tag) > 0 { name = tag } //值信息 vField := v.Field(i) vFieldValue := vField.Interface() //拼接json if t.Field(i).Type.Kind() == reflect.String { jsonStr += fmt.Sprintf("\"%s\":\"%v\"", name, vFieldValue) } else { jsonStr += fmt.Sprintf("\"%s\":%v", name, vFieldValue) } if i != numField - 1 { jsonStr += "," } } jsonStr = "{" +jsonStr + "}" } return }
测试代码
package main import ( "fmt" "oldBoy/day9/json_reflect" ) type User struct { Name string `json:"name"` Age int `json:"age"` Sex string `json:"sex"` } func main() { var a string = "hello abc" jsonStr := json_reflect.Marshals(a) fmt.Printf(jsonStr) var user User user.Name = "aaa" user.Age = 10 user.Sex = "male" jsonStr = json_reflect.Marshals(user) fmt.Printf(jsonStr) }
相关推荐
边城白衣 2020-09-10
guangmingsky 2020-06-01
狼窝 2020-04-06
shangs00 2020-02-01
zhglinux 2019-12-25
缘起宇轩阁 2019-12-24
zuihaobushi 2019-12-04
free0day 2019-10-16
rookieding 2011-03-04
opera 2013-12-26
无所畏惧 2019-03-22
道行尚浅老道 2019-03-21
84590592 2010-06-28
云端轻躺 2010-08-02
zhangdell 2019-06-30
jiuweideqixu 2012-05-21
mowengaoboa 2012-04-26
阳光丶不锈 2011-01-04
dingchaochao0 2019-06-26