標籤:Go語言中的反射機制reflect Go語言反射機制 Go語言reflect
go的反射機制是要通過介面來進行的,而類似於Java的Object的空介面可以和任何類型進行互動,因此對基礎資料型別 (Elementary Data Type)等的反射也直接利用了這一特點。
package mainimport ( "fmt" "reflect")type Student struct { Name string Age int Sex uint // 0-女性,1-男性 Address string}func (stu Student) Print() { sex := "女" if stu.Sex == 1 { sex = "男" } fmt.Printf("姓名:%s,年齡:%d,性別:%s,地址:%s", stu.Name, stu.Age, sex, stu.Address)}func (stu Student) Say(content string) string{ return fmt.Sprintf("%s說:%s", stu.Name, content)}func main() { // ============================================================操作基礎資料型別 (Elementary Data Type) var a1 int = 1 var a2 string = "中國" var a3 = [...]byte{1, 2, 3} // 數組 var a4 = []int{5, 6, 7} // 切片 var a5 = map[string]int{"china":1, "usa":2} // Map // 轉化成reflect對象,reflect.Type和reflect.Value // TypeOf()返回的資料類型是*reflect.rtype,ValueOf()返回的資料類型是reflect.Value t1 := reflect.TypeOf(a1); v1 := reflect.ValueOf(a1) t2 := reflect.TypeOf(a2); v2 := reflect.ValueOf(a2) t3 := reflect.TypeOf(a3); v3 := reflect.ValueOf(a3) t4 := reflect.TypeOf(a3); v4 := reflect.ValueOf(a4) t5 := reflect.TypeOf(a3); v5 := reflect.ValueOf(a5) fmt.Println("a1====", t1, v1) fmt.Println("a2====", t2, v2) fmt.Println("a3====", t3, v3) fmt.Println("a4====", t4, v4) fmt.Println("a5====", t5, v5) fmt.Println() // 取值 fmt.Println("a1的值:", v1.Int()) fmt.Println("a2的值:", v2.String()) fmt.Println("a3中下標為1的元素的值:", v3.Index(1)) fmt.Println("a4中下標為1的元素的值:", v4.Index(1)) fmt.Println("a4中取[1,3)的子切片:", v4.Slice(1, 3)) fmt.Println("a5中所有key:", v5.MapKeys()) fmt.Print("遍曆a5中的value:") for _, key := range v5.MapKeys() { fmt.Print(key, "====", v5.MapIndex(key), "\t") } fmt.Println() fmt.Println() // 擷取類型 fmt.Println("a1的類型:", v1.Type()) fmt.Println("a2的類型:", v2.Type()) fmt.Println("a3的類型:", v3.Type()) fmt.Println("a4的類型:", v4.Type()) fmt.Println("a5的類型:", v5.Type()) fmt.Println() // Kind類型判斷,Kind() fmt.Println("a1的類型是否為int:", v1.Kind() == reflect.Int) fmt.Println("a2的類型是否為string:", v2.Kind() == reflect.String) fmt.Println("a3的類型是否為array:", v3.Kind() == reflect.Array) fmt.Println("a4的類型是否為slice:", v4.Kind() == reflect.Slice) fmt.Println("a5的類型是否為map:", v5.Kind() == reflect.Map) fmt.Println() // 介面類型變數,Interface是擷取該value的值,返回的是一個interface對象 fmt.Printf("a1====%T\t%v\n", v1.Interface(), v1.Interface()) fmt.Printf("a2====%T\t%v\n", v2.Interface(), v2.Interface()) fmt.Printf("a3====%T\t%v\n", v3.Interface(), v3.Interface()) fmt.Printf("a4====%T\t%v\n", v4.Interface(), v4.Interface()) fmt.Printf("a5====%T\t%v\n", v5.Interface(), v5.Interface()) fmt.Println() // 判斷是否可以修改 fmt.Println("a1通過反射是否可以進行修改:", v1.CanSet()) fmt.Println("a2通過反射是否可以進行修改:", v2.CanSet()) fmt.Println("a3通過反射是否可以進行修改:", v3.CanSet()) fmt.Println("a4通過反射是否可以進行修改:", v4.CanSet()) fmt.Println("a5通過反射是否可以進行修改:", v5.CanSet()) fmt.Println() // 修改,必須傳指標,且調用Elem() vv1 := reflect.ValueOf(&a1).Elem() fmt.Printf("vv1的類型:%T,a1現在是否可以通過:%v\n", vv1, vv1.CanSet()) vv2 := reflect.ValueOf(&a2).Elem() vv3 := reflect.ValueOf(&a3).Elem() vv4 := reflect.ValueOf(&a4).Elem() vv5 := reflect.ValueOf(&a5).Elem() vv1.SetInt(100) // 修改 vv2.SetString("美國") var temp byte = 90 vv3.Index(0).Set(reflect.ValueOf(temp)) // 必須傳reflect.Value類型 vv4.Index(0).SetInt(900) // 必須傳reflect.Value類型 vv5.SetMapIndex(reflect.ValueOf("china"), reflect.ValueOf(111)) fmt.Println("a1修改後的值:", a1) fmt.Println("a2修改後的值:", a2) fmt.Println("a3修改後的值:", a3) fmt.Println("a4修改後的值:", a4) fmt.Println("a5修改後的值:", a5) // ============================================================操作結構體 stu := Student{"李四", 18, 1, "中國北京市天安門10000號"} // 轉化成reflect對象,reflect.Type和reflect.Value st1 := reflect.TypeOf(stu) sv1 := reflect.ValueOf(stu) fmt.Println(st1, "====", sv1) // 擷取結構體名稱 fmt.Println(st1.Name()) // 判斷Kind類型 fmt.Println(st1.Kind() == reflect.Struct) // 擷取結構體中欄位數量 fmt.Println(st1.NumField()) // 擷取結構體中每個欄位的值 for i := 0 ; i < st1.NumField() ; i++ { fieldName := st1.Field(i).Name // 取欄位名 fieldType := st1.Field(i).Type fieldVal := sv1.Field(i).Interface() // 取值 fmt.Printf("欄位名:%v,類型:%v,值:%v\n", fieldName, fieldType, fieldVal) } // 擷取結構體的方法數量 fmt.Println(st1.NumMethod()) // 遍曆所有方法的名稱和類型 for i := 0 ; i < st1.NumMethod() ; i++ { method := st1.Method(i) fmt.Println(method.Name, "====", method.Type) } // 通過反射執行方法 m1 := sv1.MethodByName("Print") m1.Call(nil)// 不帶參數和傳回值 fmt.Println() m2 := sv1.MethodByName("Say") params := []reflect.Value{reflect.ValueOf("你好啊!")} res := m2.Call(params) // 帶參數和傳回值,參數是reflect.Value的切片,傳回值也一樣 fmt.Println(res[0].String())}
Go語言中的反射機制reflect