golang之反射常用函數介紹

目錄

1、通過反射獲取到傳入變量的type,值、kind

2、變量、interface{},reflect.Value相互轉化

3、反射獲取結構體內容

4、反射最佳實踐


 

反射可以在運行時動態獲取變量的各種信息,比如變量的類型、類別。如果是結構體變量,還可以獲取到結構體本身的信息(包括結構體字段、方法)。通過反射,可以修改變量的值,可以調用關聯的方法

1、通過反射獲取到傳入變量的type,值、kind

Type是類型,Kind是類別【最原始的數據類型】,Type和Kind可能相同,也可能不同

  • Eg: var num int = 10,num的Type是int,Kind也是int
  • Eg: var stu Student,stu 的Type是model.Student,Kind是struct

  • reflect.TypeOf(變量名):獲取變量的類型,返回reflect.Type類型
  • reflect.ValueOf(變量名):獲取變量的值,返回reflect.Value類型reflect.Value,是一個結構體類型

兩種方式可以獲取到Kind

  • reflect.TypeOf(變量名).Kind()
  • reflect.ValueOf(變量名).Kind()

注意:如果傳入的interface是10,那麼它的值類型是reflect.Value,不等同於int,如果進行運算,需要先

2、變量、interface{},reflect.Value相互轉化

上述將interface{}轉化成需要類型的方式除了斷言(加入對返回值的判斷)外還可以採用switch方式

  • interface{} -> reflect.Value:rValue := reflect.ValueOf(b)
  • reflect.Value -> interface{}:iV := rValue.Interface()
  • interface{} -> 變量:num3 := iV.(int)

3、反射獲取結構體內容

獲取結構體字段

獲取方法並調用:

修改值:

4、反射最佳實踐

type Monster struct {
	Name  string  `json:"name"`
	Age   int     `json:"monster_age"`
	Score float32 `json:"成績"`
	Sex   string
}

//返回兩個數的和
func (s Monster) GetSum(n1, n2 int) int {
	return n1 + n2
}

//接收四個值,給s賦值
func (s Monster) Set(name string, age int, score float32, sex string) {
	s.Name = name
	s.Age = age
	s.Score = score
	s.Sex = sex
}

//顯示s的值
func (s Monster) Print() {
	fmt.Println("----start----")
	fmt.Println(s)
	fmt.Println("----end----")
}

//使用反射獲取結構體內容
func TestStruct(a interface{}) {
	typ := reflect.TypeOf(a)
	val := reflect.ValueOf(a)
	kd := val.Kind()
	if kd != reflect.Struct {
		fmt.Println("expect struct")
		return
	}
	//獲取到該結構體有幾個字段
	num := val.NumField()
	fmt.Printf("struct has %d fields\n", num)
	
	//變量結構體的所有字段
	for i := 0; i < num; i++ {
		fmt.Printf("Filed %d:值爲=%v\n", i, val.Field(i))
		//獲取到struct標籤:注意需要通過reflect.Type來獲取tag
		tagVal := typ.Field(i).Tag.Get("json")
		//如果該字段屬於tag標籤就顯示,否則就不顯示
		if tagVal != "" {
			fmt.Printf("Filed %d:tag 爲=%v\n", i, tagVal)
		}
	}
	//獲取到該結構體有多少個方法
	numOfMethod := val.NumMethod()
	fmt.Printf("struct has %d methods\n", numOfMethod)
	
	//var  params []reflect.Value
	//方法的默認順序是按照函數名的排序
	val.Method(1).Call(nil) //獲取到第二個方法,調用它
	
	//調用結構體的第一個方法
	var params []reflect.Value
	params = append(params, reflect.ValueOf(10))
	params = append(params, reflect.ValueOf(40))
	res := val.Method(0).Call(params) //Call方法的參數是 []reflect.Value,返回 []reflect.Value
	fmt.Println("res=", res[0].Int()) //返回的結果是[]reflect.Value
}

//修改值
func UpdateStruct(a interface{}) {
	val := reflect.ValueOf(a)
	val.Elem().Field(0).SetString("白象精")
}
func main() {
	var a Monster = Monster{
		Name:  "黃鼠狼精",
		Age:   400,
		Score: 30.8,
	}
	TestStruct(a)
	
	UpdateStruct(&a)
	fmt.Println(a)
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章