1. 程式人生 > 其它 >Plug and Play Language Models

Plug and Play Language Models

go 反射

1.1 反射介紹

反射就是在執行期間(不是編譯期間)探知物件的型別資訊和記憶體結構、更新變數、呼叫它們的方法

1.1.1 反射的使用場景

  • 函式的引數型別是interface{},需要在執行時對原始型別進行判斷,針對不同的型別採取不同的處理方式。比如json.Marshal(v interface{})。
  • 在執行時根據某些條件動態決定呼叫哪個函式,比如根據配置檔案執行相應的運算元函式

1.2 反射弊端

  • 程式碼難以閱讀,難以維護。
  • 編譯期間不能發現型別錯誤,覆蓋測試難度很大,有些bug需要到線上執行很長時間才能發現,可能造成嚴重用後果。
  • 反射效能很差,通常比正常程式碼慢一到兩個數量級。在對效能要求很高,或大量反覆呼叫的程式碼塊裡建議不要使用反射。

1.3 反射基礎型別

1.3.1 reflect.Type

reflect.Type用於獲取型別相關的資訊

type Type interface {
	Method(int) Method  //第i個方法
	MethodByName(string) (Method, bool) //根據名稱獲取方法
	NumMethod() int  //方法的個數
	Name() string   //獲取結構體名稱
	PkgPath() string //包路徑
	Size() uintptr  //佔用記憶體的大小
	String() string  //獲取字串表述
	Kind() Kind  //資料型別
	Implements(u Type) bool  //判斷是否實現了某介面
	AssignableTo(u Type) bool  //能否賦給另外一種型別
	ConvertibleTo(u Type) bool  //能否轉換為另外一種型別
	Elem() Type  //解析指標
	Field(i int) StructField  //第i個成員
	FieldByIndex(index []int) StructField  //根據index路徑獲取巢狀成員
	FieldByName(name string) (StructField, bool)  //根據名稱獲取成員
	FieldByNameFunc(match func(string) bool) (StructField, bool)  //
	Len() int  //容器的長度
	NumIn() int  //輸出引數的個數
	NumOut() int  //返回引數的個數
}

1.3.2 reflect.Value

reflect.Value獲取、修改原始資料型別裡的值.

type Value struct {
	// 代表的資料型別
	typ *rtype
	// 指向原始資料的指標
	ptr unsafe.Pointer
}

1.4 反射型別

1.4.1 reflect.Type

1.4.1.1 Kind && String 案例
func fansheinit1() {
	typeI := reflect.TypeOf(1)
	typeS := reflect.TypeOf("hello")
	fmt.Println(typeI)
	fmt.Println(typeS)
	fmt.Println(typeI.String())
	fmt.Println(typeS.String())
	fmt.Println(typeI.Kind() == reflect.Int)
	fmt.Println(typeS.Kind() == reflect.String)
}