Plug and Play Language Models
阿新 • • 發佈:2022-03-29
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) }