Golang學習筆記-反射

反射讓我們可以在運行時獲取對象的類型信息,比如查看一個結構體有多少字段,查看函數的入參類型和返回值類型等。

Go提供了reflect.TypeOf()和reflect.ValueOf獲取任意對象的reflect.Value和reflect.Type,其中reflect.Type是一個接口類型,該接口提供了很多方法讓我們獲取類型信息,而reflect.Value是一個結構體,它提供了很多方法讓我們獲取或者寫入reflect.Value結構體中存儲的數據。

獲取類型信息

package main

import (
	"fmt"
	"reflect"
)

type Person struct {
	name string
	height int
}

func (person Person) AddHeight(height int)  string{
	person.height+=height
	return string(person.height)
}

func main(){
	//遍歷結構體字段
	person:=Person{}
	valueType:=reflect.TypeOf(person)
	for i:=0;i<valueType.NumField();i++{
		field:=valueType.Field(i)
		fmt.Println(field.Name,field.Type)
	}
	//遍歷結構體導出的方法
	for i:=0;i<valueType.NumMethod();i++{
		method:=valueType.Method(i)
		fmt.Println(method.Name)
	}
	//遍歷函數參數和返回值
	valueType=reflect.TypeOf(Person{}.AddHeight)
	for i:=0;i<valueType.NumIn();i++{
		arg:=valueType.In(i)
		fmt.Println(arg)
	}
	for i:=0;i<valueType.NumOut();i++{
		result:=valueType.Out(i)
		fmt.Println(result)
	}

}

底層類型

使用Kind方法可以獲取類型的底層類型,Go提供了以下底層類型:

const (
	Invalid Kind = iota
	Bool
	Int
	Int8
	Int16
	Int32
	Int64
	Uint
	Uint8
	Uint16
	Uint32
	Uint64
	Uintptr
	Float32
	Float64
	Complex64
	Complex128
	Array
	Chan
	Func
	Interface
	Map
	Ptr
	Slice
	String
	Struct
	UnsafePointer
)

通過reflect.Value還原對象

使用Interface()方法可以將reflect.Value還原成接口類型,然後再強轉一次就能還原成原本的類型。

func main(){
	value := reflect.ValueOf(1)
	fmt.Println(value.Interface().(int))
}

通過reflect.Value修改對象

如果想通過reflect.Value修改對象,那麼reflect.ValueOf()需要傳遞對象的地址,然後通過Elem()方法找到這個指針指向的值才能修改,reflect.Value提供了CanSet()方法幫助我們判斷是否可以修改該對象。

func main(){
	name:="xiongya"
	nameValue:=reflect.ValueOf(&name)
	nameValue.Elem().SetString("xy")
	fmt.Println(name)
}

動態調用方法

利用反射動態調用方法時參數和返回值都是reflect.Value切片。

package main

import (
	"fmt"
	"reflect"
	"strconv"
)

type Person struct {
	name string
	height int
}

func (person Person) AddHeight(height int)  string{
	person.height+=height
	return strconv.Itoa(person.height)
}

func main(){
	person:=Person{"xiao hong",100}
	value:=reflect.ValueOf(person)
	method:=value.MethodByName("AddHeight")
	if method.IsValid(){
		args:=[]reflect.Value{reflect.ValueOf(10)}
		fmt.Println(method.Call(args))
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章