<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
// SumInts 將map的值相加,如果需要新增的資料型別不同,那麼就需要定義兩個 func SumInts(m map[string]int64) int64 { var s int64 for _, v := range m { s += v } return s } func SumFloats(m map[string]float64) float64 { var s float64 for _, v := range m { s += v } return s }
如果使用泛型的話只需要定義泛型方法即可(如果報一下編譯錯誤的話,是idea版本過低,升級版本即可,但是執行沒有問題)
func main() { ints := make(map[string]int64, 5) ints["name"] = 5 ints["value"] = 6 floats := make(map[string]float64, 5) floats["name"] = 5.6 floats["value"] = 6.5 fmt.Printf("Gnneric sums: %v and %vn", SumIntsOrFloats[string, int64](ints), SumIntsOrFloats[string, float64](floats)) //可以將型別刪除 fmt.Printf("Gnneric sums: %v and %vn", SumIntsOrFloats(ints), SumIntsOrFloats(floats)) } //SumIntsOrFloats 定義泛型方法 func SumIntsOrFloats[K comparable, V int64 | float64](m map[K]V) V { var s V for _, v := range m { s += v } return s }
//型別約束 type Number interface { int64 | float64 }
//進行型別約束時就可以使用當前類 func SumIntsNumbers[K comparable, V Number](m map[K]V) V { var s V for _, v := range m { s += v } return s }
func main() { fmt.Println(Get(12)) } //go中不能直接將泛型與switch使用 func Get[T any](t T) T { var ti interface{} = &t switch v := ti.(type) { case *int: *v = 18 } return t }
使用泛型定義Json解析方法
//根據傳入的型別通過反射獲取到型別以及值 func typeFunc[E any](v any, e *E) *E { valueOf := reflect.ValueOf(v) typeOf := reflect.TypeOf(v) if k := typeOf.Kind(); k == reflect.Slice { json.Unmarshal(valueOf.Bytes(), e) } return e } func main() { user1 := &User{} user1 = typeFunc[User](marshal, user1) fmt.Printf("%+v", user1) }
Golang提供了一種機制,在編譯時不知道型別的情況下,可更新變數、執行時檢視值、呼叫方法以及直接對他們的佈局進行操作的機制,稱為反射。
方法 | 說明 | 返回 |
---|---|---|
reflect.ValueOf() | 獲取輸入引數介面中的資料的值,如果未空則返回 0,注意當前方法會使物件逃逸到堆空間當中 | 返回的是 Value 物件 |
reflect.TypeOf() | 動態獲取輸入引數介面中的值的型別,如果為空則返回 nil | 返回的是 Type 物件 |
Value
type Value struct { typ *rtype //儲存型別的值 ptr unsafe.Pointer //指標型別 flag //獲取到值的指向地址,用於通過反射修改值 Elem() Type //給value設定值 Set() }
Type
type Type interface { //根據索引獲取到方法 Method(int) Method //通過名稱獲取到方法 MethodByName(string) (Method, bool) //獲取到方法的數量 NumMethod() int //獲取結構名稱 Name() string //獲取包路徑 PkgPath() string //獲取到當前型別 Kind() Kind //判斷當前型別是否實現了介面 Implements(u Type) bool //以位為單位返回型別的x Bits() int //獲取到屬性值的型別,型別必須是:Array、Chan、Map、Pointer、Slice,否則報錯 Elem() Type //獲取到指定所以的值 Field(i int) StructField //獲取到對應索引的巢狀欄位 FieldByIndex(index []int) StructField //通過名稱獲取到對應的欄位 FieldByName(name string) (StructField, bool) FieldByNameFunc(match func(string) bool) (StructField, bool) ..... }
func stringReflect() { name := "這是第一個反射字串" valueOf := reflect.ValueOf(name) typeOf := reflect.TypeOf(name) fmt.Println(valueOf) fmt.Println(typeOf) }
type Name struct { Name string Age string `use:"Ok"` } func (n Name) Show() { fmt.Println(n.Name) } func structReflect() { name := Name{ Name: "這是反射結構", } valueOf := reflect.ValueOf(name) typeOf := reflect.TypeOf(name) fmt.Printf("value值:%+vn", valueOf) fmt.Printf("型別名稱:%sn", typeOf.Name()) methodNum := typeOf.NumMethod() fmt.Printf("獲取到方法的數量:%d", methodNum) for i := 0; i < methodNum; i++ { method := typeOf.Method(i) fmt.Printf("%vt", method.Name) } fmt.Println() methodByName, _ := typeOf.MethodByName("Show") fmt.Printf("根據Show查詢指定方法:%vn", methodByName) //判斷是否實現了當前介面,因為介面型別不能建立範例,所以把 nil 強制轉為 *IName 型別 implements := typeOf.Implements(reflect.TypeOf((*IName)(nil)).Elem()) fmt.Printf("當前型別:%s,是否實現介面:%s,%vn", typeOf.Name(), "IName", implements) fieldNum := typeOf.NumField() for i := 0; i < fieldNum; i++ { field := typeOf.Field(i) fmt.Printf("欄位名稱:%vt", field.Name) if lookup, ok := field.Tag.Lookup("use") ; ok { fmt.Printf("獲取標籤:%v", lookup) } } }
func setValue() { name := Name{ Name: "這是反射結構", } valueOf := reflect.ValueOf(&name) fmt.Printf("設定值之前:%+vn", valueOf) //獲取到地址值 valueOf = valueOf.Elem() name1 := Name{ Name: "這是通過反射設定的值", } valueOf.Set(reflect.ValueOf(name1)) fmt.Printf("設定值之後:%+vn", valueOf) //修改欄位值 fieldValueOf := valueOf.FieldByName("Name") fieldValueOf.SetString("這是修改欄位之後的值") fmt.Printf("修改欄位之後:%vn", name.Name) //呼叫方法 methodByName := valueOf.MethodByName("Show") values := make([]reflect.Value, 0) methodByName.Call(values) }
func judgeType() { name := Name{Name: "123"} typeOf := reflect.TypeOf(name) switch typeOf.Kind() { case reflect.Slice: fmt.Println("切面") case reflect.Array: fmt.Println("陣列") case reflect.Struct: fmt.Println("結構體") } //判斷具體型別 var ti interface{} = &name switch ti.(type) { case *Name: fmt.Printf("%+vn", ti) } }
到此這篇關於Golang泛型與反射的應用詳解的文章就介紹到這了,更多相關Golang泛型與反射內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45