反射
反射:可以在运行时动态获取变量的相关信息
? Import (“reflect”)
reflect.TypeOf,获取变量的类型,返回reflect.Type类型
reflect.ValueOf,获取变量的值,返回reflect.Value类型
reflect.Value.Kind,获取变量的类别,返回一个常量
reflect.Value.Interface(),转换成interface{}类型
reflect.ValueOf(x).Float()
reflect.ValueOf(x).Int()
reflect.ValueOf(x).String()
reflect.ValueOf(x).Bool()
通过反射的来改变变量的值
reflect.Value.SetXX相关方法,比如:
reflect.Value.SetFloat(),设置浮点数
reflect.Value.SetInt(),设置整数
reflect.Value.SetString(),设置字符串
package main import ( "fmt" "reflect" ) type Student struct { Name string Age int Score float32 } func test(b interface{}) { //t是b的一个拷贝,修改t,b不会修改! t := reflect.TypeOf(b) //获取变量的类型,返回reflect.Type类型 fmt.Println(t) v := reflect.ValueOf(b) //获取变量的值,返回reflect.Value类型 fmt.Println(v) k := v.Kind() //获取变量的类别,返回一个常量 fmt.Println(k) iv := v.Interface() stu, ok := iv.(Student) if ok { fmt.Printf("%v %T\n", stu, stu) } } func testInt(b interface{}) { val := reflect.ValueOf(b) fmt.Println(val.Elem()) val.Elem().SetInt(100) //val.Elem()用来获取指针指向的变量,相当于: //var a *int; //*a = 100 c := val.Elem().Int() fmt.Printf("get value interface{} %d\n", c) fmt.Printf("string val:%d\n", val.Elem().Int()) } func main() { var a Student = Student{ Name: "stu01", Age: 18, Score: 92, } test(a) var b int = 1 b = 200 testInt(&b) fmt.Println(b) }
reflect.Value.NumField()获取结构体中字段的个数
reflect.Value.Method(n).Call来调用结构体中的方法
package main import ( "fmt" "reflect" ) type NotknownType struct { s1 string s2 string s3 string } func (n NotknownType) String() string { return n.s1 + "-" + n.s2 + "-" + n.s3 } var secret interface{} = NotknownType{"greg", "learn", "go"} func main() { value := reflect.ValueOf(secret) // <main.NotknownType Value> typ := reflect.TypeOf(secret) // main.NotknownType fmt.Println(value,typ) knd := value.Kind() // struct fmt.Println(knd) for i := 0; i < value.NumField(); i++ { //value.Field(i).SetString("ningxin") fmt.Printf("Field %d: %v\n", i, value.Field(i)) } results := value.Method(0).Call(nil) fmt.Printf("%T\n",results) fmt.Println(results) }
反射回调函数和方法
package main import ( "fmt" "reflect" ) type Student struct { Name string Age int Score float64 Sex string } func (s Student) Print() { fmt.Println("---start----") fmt.Println(s) fmt.Println("---end----") } func (s Student) Set(name string, age int, score float64, sex string) { s.Name = name s.Age = age s.Score = score s.Sex = sex fmt.Println(s) } func TestStruct(a interface{}) { val := reflect.ValueOf(a) kd := val.Kind() if kd != reflect.Ptr && val.Elem().Kind() == reflect.Struct { fmt.Println("expect struct") return } num := val.Elem().NumField() val.Elem().Field(0).SetString("greg") for i := 0; i < num; i++ { fmt.Printf("%d %v\n", i, val.Elem().Field(i).Kind()) } fmt.Printf("struct has %d fields\n", num) numOfMethod := val.Elem().NumMethod() fmt.Printf("struct has %d methods\n", numOfMethod) val.Elem().Method(0).Call(nil) params := make([]reflect.Value,4) params[0]=reflect.ValueOf("hhhhhhhhh") params[1]=reflect.ValueOf(188888888) params[2]=reflect.ValueOf(59.99999) params[3]=reflect.ValueOf("male") //fmt.Println(params) val.Elem().Method(1).Call(params) } func main() { var a Student = Student{ Name: "ningxin", Age: 18, Score: 92.8, } fmt.Println(a) TestStruct(&a) }
json序列化是通过反射实现的
package main import ( "encoding/json" "fmt" "reflect" ) type Student struct { Name string `json:"student_name"` Age int Score float32 Sex string } func (s Student) Set(name string, age int, score float32, sex string) { s.Name = name s.Age = age s.Score = score s.Sex = sex } func Tagtest(a interface{}) { tye := reflect.TypeOf(a) fmt.Println("///////////",tye) fmt.Println(tye.Elem()) fmt.Println(tye.Elem().Field(0)) fmt.Println(tye.Elem().Field(0).Tag) tag := tye.Elem().Field(0).Tag.Get("json") fmt.Printf("tag=%s///////////\n", tag) } func main() { var a Student = Student{ Name: "stu01", Age: 18, Score: 92.8, } result, _ := json.Marshal(a) fmt.Println("json result:", string(result)) Tagtest(&a) fmt.Println(a) }