reflect反射
1.使用情境
當一些類型未知,有多種類型需要統一處理時,考慮使用反射來做多種情況的統一判斷處理。
反射讀取資料:
reflect常見類型
reflect.Int,reflect.Int8,reflect.Int16,reflect.Int32,reflect.Int64 reflect.Uint,reflect.Uint8,reflect.Uint16,reflect.Uint32,reflect.Uint64,reflect.Uintptr reflect.Bool reflect.String reflect.Chan,reflect.Func,reflect.Ptr,reflect.Slice,reflect.Map,reflect.Array,reflect.Struct: reflect.Invalid reflect.Interface
reflect.TypeOf()
將一個具體的值,轉為介面類型!返回具體的類型。
注意格式輸出時控制符t:=reflect.TypeOf(3) fmt.Println(t.String()) fmt.Printf("%s\n",t.String()) fmt.Printf("%v\n",t)
x := 4 v := reflect.ValueOf(x) //反射拿到Value類型 fmt.Println(v) //4 t := v.Type() //Value實現了各種方法 fmt.Println(t.String()) //int
v := reflect.ValueOf(3) //拿到Value類型到資料值,類型為Value fmt.Println(v) //3 fmt.Printf("%T", v) //reflect.Value fmt.Println(v.Int()) //將Value類型轉換成特定類型 //3 x := v.Interface() //將Value轉成介面類型 i := x.(int) fmt.Printf("%T\n", i) m, ok := x.(int) //類型斷言,取出其值 ,並轉成斷言的類型 if !ok { fmt.Println("類型轉換錯誤") } fmt.Printf("%d,%T", m, m) //3,int
var value interface{} fmt.Println(reflect.ValueOf(value).Kind()) //slice fmt.Println(reflect.TypeOf(value)) //[]int
反射修改資料
我們可以通過調用reflect.ValueOf(&x).Elem(),來擷取任意變數x對應的可取地址的Value。
x := 2 d := reflect.ValueOf(&x).Elem() // d refers to the variable x px := d.Addr().Interface().(*int) // px := &x *px = 3 // x = 3 fmt.Println(x) // "3"
慎用反射
- 1.反射代碼比較脆弱,不會在構建時報錯,只有在真正啟動並執行時候才會拋出Panic
- 難讀不易懂,不能做靜態類型檢查
- 反射代碼運行速度慢
Example
將Value類型轉成interface
if _, ok := req.(reflect.Value); ok { req = req.(reflect.Value).Interface() }
判斷比對interface類型:
var req interface{} switch req.(type) { case int: fmt.Println("*") }