1. 程式人生 > >Go語言之反射

Go語言之反射

lec mon \n otto switch set 接口 app solid

變量與反射

1.變量的內在機制

A.類型信息,這部分是元信息,是預先定義好的,比如

  1: var arr [10]int
  2: arr[0] = 10
  3: arr[1] = 20
  4: arr[2] = 30
  5: arr[3] = 40
  6: arr[4] = 50

B.值類型,這部分是程序運行過程中,動態改變的.

  1: type Animal struct {
  2:     Name string
  3:     age int
  4: }
  5: 
  6: var a Animal

2.反射與空接口

A. 空接口可以存儲任何類型的變量

B.那麽給你一個空接口,怎麽知道裏面存儲的是什麽東西

c.在運行時動態的獲取一個變量的類型信息和值類型,就叫反射

3.怎麽分析

A.內置包 reflect

B.獲取類型信息:reflect.TypeOf

C:獲取值信息 reflect.ValueOf

基本數據類型分析(a是一個空接口變量)

  1: package main
  2: 
  3: import (
  4: 	"fmt"
  5: 	"reflect"
  6: )
  7: 
  8: func reflect_example(a interface{}) {
  9: 	t := reflect.TypeOf(a)
 10: 	fmt.Printf("type of a: %v\n
", t)
 11: }
 12: 
 13: func main() {
 14: 	var x float64 = 3.4
 15: 	reflect_example(x)
 16: 	var y float32 = 3.2
 17: 	reflect_example(y)
 18: }
打印
  1: type of a: float64
  2: type of a: float32

t.Kind()直接獲取類型,結果為reflect.Int64,reflect.String等…可以用swtich來判斷

reflect.ValueOf獲取變量的值相關信息:

  1: var x float64 = 3.4
  2: v := reflect.ValueOf(x)
  3: // 和reflect.TypeOf功能是一樣的
  4: fmt.Println("type:", v.Type())
  5: fmt.Println("kind is float64:", v.kind()==reflect.Float64)
  6: 
  7: fmt.Println("value:", v.Float())

通過反射設置變量的值

  1: func reflect_set_value(a interface{}){
  2: 	t := reflect.ValueOf(a)
  3: 	k := t.Kind()
  4: 	switch k {
  5: 	case reflect.Int64:
  6: 		t.SetInt(100)
  7: 		fmt.Println("typeof is int64")
  8: 	case reflect.Float64:
  9: 		t.SetFloat(6.6)
 10: 		fmt.Println("typeof is Float64")
 11: 	case reflect.Ptr:
 12: 		//t.Elem()等同於*t
 13: 		t.Elem().SetFloat(6.6)
 14: 	}
 15: }
 16: func main() {
 17: 	var x float64 = 9.9
 18: 	// 註意這裏傳入的是x的指針
 19: 	reflect_set_value(&x)
 20: 	fmt.Println("x value:",x)
 21: }

結構體反射

獲取結構體類型相關信息

  1: type student struct {
  2: 	Name string
  3: 	Sex int
  4: 	Age int
  5: }
  6: func main()  {
  7: 	var a student
  8: 	v := reflect.ValueOf(a)
  9: 	t := v.Type()
 10: 	// t := reflect.TypeOf(a)
 11: 	kind := t.Kind()
 12: 	switch kind {
 13: 	case reflect.Int64:
 14: 		fmt.Println("")
 15: 	case reflect.Float64:
 16: 		fmt.Println("")
 17: 	case reflect.Struct:
 18: 		fmt.Println("is struct")
 19: 		fmt.Println("field num", v.NumField())
 20: 		for i:=0;i<v.NumField();i++ {
 21: 			field := v.Field(i)
 22: 			fmt.Printf("name-%s, type-%v value-%v\n", t.Field(i).Name, field.Type(), field.Interface())
 23: 		}
 24: 	}

設置結構體字段的值

  1: func main()  {
  2: 	var a student
  3: 	v := reflect.ValueOf(&a)
  4: 	v.Elem().Field(0).SetString("stu01")
  5: 	v.Elem().FieldByName("Sex").SetInt(2)
  6: 	v.Elem().FieldByName("Age").SetInt(18)
  7: 	fmt.Println("a:", a)

結構體方法調用

  1: type Student struct {
  2: 	Name string
  3: 	Sex int
  4: 	Age int
  5: }
  6: func (s *Student) SetName(name string)  {
  7: 	s.Name = name
  8: }
  9: func (s *Student) Print() {
 10: 	fmt.Println(s.Name)
 11: }
 12: func main()  {
 13: 	var a Student
 14: 	v := reflect.ValueOf(&a)
 15: 	t := v.Type()
 16: 	
 17: 	// 獲取方法的具體信息
 18: 	fmt.Println("method numbers", t.NumMethod())
 19: 	for i:=0; i<t.NumMethod();i++ {
 20: 		method := t.Method(i)
 21: 		fmt.Printf("name:%s type:%s\n", method.Name, method.Type)
 22: 	}
 23: 	// 有參數的方法
 24: 	m := v.MethodByName("SetName")
 25: 	var arg1 []reflect.Value
 26: 	name := "stu1"
 27: 	// 將string轉化成reflect.Value類型
 28: 	nameVal := reflect.ValueOf(name)
 29: 	arg1 = append(arg1, nameVal)
 30: 	m.Call(arg1)
 31: 
 32: 	// 無參數的方法
 33: 	m1 := v.MethodByName("Print")
 34: 	var arg2 []reflect.Value
 35: 	m1.Call(arg2)

結果

  1: method numbers 2
  2: name:Print type:func(*main.Student)
  3: name:SetName type:func(*main.Student, string)
  4: stu1

tag信息獲取

  1: type Student struct {
  2: 	Name string `json:"name"`
  3: }
  4: 
  5: func main()  {
  6: 	var a Student
  7: 	v := reflect.ValueOf(&a)
  8: 	t := v.Type()
  9: 	field0 := t.Elem().Field(0)
 10: 	fmt.Println("tag json =",field0.Tag.Get("json"))
 11: }

總結

反射就是在運行程序中可以動態地獲取一個變量的類型信息和值信息

Go語言之反射