自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Go泛型系列:Slices 包講解

開發(fā) 后端
目前,Go 泛型的主要設計者 ianlancetaylor 完成了 slices 和 maps 包的開發(fā),代碼提交到了 golang.org/x/exp 中,如果經(jīng)過使用、討論等,社區(qū)認可后,預計在 1.19 中會合入標準庫中。

[[437049]]

大家好,我是 polarisxu。

前段時間,Russ Cox 明確了泛型相關的事情,原計劃在標準庫中加入泛型相關的包,改放到 golang.org/x/exp 下。

目前,Go 泛型的主要設計者 ianlancetaylor 完成了 slices 和 maps 包的開發(fā),代碼提交到了 golang.org/x/exp 中,如果經(jīng)過使用、討論等,社區(qū)認可后,預計在 1.19 中會合入標準庫中。

今天,通過學習 slices 包,掌握 Go 泛型的使用方法。

01 為什么增加 slices 包

標準庫有 bytes 和 strings 包,分別用來處理 []byte 和 string 類型,提供了眾多方便的函數(shù),但對普通的 slice,卻沒有相關的包可以使用。

比如 bytes 和 strings 都有 Index 函數(shù),用來在 []byte 或 string 查找某個 byte 或字符串的索引。對于普通的 slice,沒法寫一大堆包來處理,只能用戶自己實現(xiàn),這也是沒有泛型的弊端。

提供 bytes 和 strings,主要是因為它們使用頻率高

現(xiàn)在有了泛型,可以實現(xiàn)一些便利的 slice 操作方法,必須要針對某一個具體類型的 slice 都實現(xiàn)一遍相同的功能。

02 constraints 包

繼續(xù)講解 slices 包之前,先看看 contraints 包。

該包定義了一組用于類型參數(shù)(泛型)的有用約束,這個包已經(jīng)確定在 Go 1.18 標準庫中包含,截止目前(2021.11.27),該包定義了 6 個約束類型:

  1. // Signed is a constraint that permits any signed integer type. 
  2. // If future releases of Go add new predeclared signed integer types, 
  3. // this constraint will be modified to include them. 
  4. type Signed interface { 
  5.  ~int | ~int8 | ~int16 | ~int32 | ~int64 
  6.  
  7. // Unsigned is a constraint that permits any unsigned integer type. 
  8. // If future releases of Go add new predeclared unsigned integer types, 
  9. // this constraint will be modified to include them. 
  10. type Unsigned interface { 
  11.  ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr 
  12.  
  13. // Integer is a constraint that permits any integer type. 
  14. // If future releases of Go add new predeclared integer types, 
  15. // this constraint will be modified to include them. 
  16. type Integer interface { 
  17.  Signed | Unsigned 
  18.  
  19. // Float is a constraint that permits any floating-point type. 
  20. // If future releases of Go add new predeclared floating-point types, 
  21. // this constraint will be modified to include them. 
  22. type Float interface { 
  23.  ~float32 | ~float64 
  24.  
  25. // Complex is a constraint that permits any complex numeric type. 
  26. // If future releases of Go add new predeclared complex numeric types, 
  27. // this constraint will be modified to include them. 
  28. type Complex interface { 
  29.  ~complex64 | ~complex128 
  30.  
  31. // Ordered is a constraint that permits any ordered type: any type 
  32. // that supports the operators < <= >= >. 
  33. // If future releases of Go add new ordered types, 
  34. // this constraint will be modified to include them. 
  35. type Ordered interface { 
  36.  Integer | Float | ~string 

前面 3 個是整型相關類型約束,F(xiàn)loat 是浮點型約束,Complex 是負數(shù)類型約束,而 Ordered 表示支持排序的類型約束,表示支持大小比較的類型。

之前文章:《Go泛型系列:Go1.18 類型約束那些事》提到,約束語法變更了,一個是 | 符號,一個是 ~,上面定義中,很多地方都用到了 ~ 符號,它表示出了類型自身,底層類型是它的類型也適用該約束。

03 slices 包詳解

目前,slices 包有 14 個函數(shù),可以分成幾組:

  • slice 比較
  • 元素查找
  • 修改 slice
  • 克隆 slice

其中,修改 slice 分為插入元素、刪除元素、連續(xù)元素去重、slice 擴容和縮容。

slice 比較

比較兩個 slice 中的元素,細分為是否相等和普通比較:

  1. func Equal[E comparable](s1, s2 []E) bool 
  2.  
  3. func EqualFunc[E1, E2 any](s1 []E1, s2 []E2, eq func(E1, E2) bool) bool 
  4.  
  5. func Compare[E constraints.Ordered](s1, s2 []E) int 
  6.  
  7. func CompareFunc[E1, E2 any](s1 []E1, s2 []E2, cmp func(E1, E2) intint 

其中 comparable 約束是語言實現(xiàn)的(因為很常用),表示可比較約束(相等與否的比較)。主要,其中的 E、E1、E2 等,只是泛型類型表示,你定義時,可以用你喜歡的,比如 T、T1、T2 等。

看一個具體的實現(xiàn):

  1. func Equal[E comparable](s1, s2 []E) bool { 
  2.  
  3. if len(s1) != len(s2) { 
  4.  
  5. return false 
  6.  
  7.  
  8. for i, v1 := range s1 { 
  9.  
  10. v2 := s2[i] 
  11.  
  12. if v1 != v2 { 
  13.  
  14. return false 
  15.  
  16.  
  17.  
  18. return true 
  19.  

沒有什么特別的,只不過把 s1、s2 當成同類型的 slice 進行操作而已。

元素查找

在 slice 中查找某個元素,分為普通的所有查找和包含判斷:

  1. func Index[E comparable](s []E, v E) int 
  2.  
  3. func IndexFunc[E any](s []E, f func(E) bool) int 
  4.  
  5. func Contains[E comparable](s []E, v E) bool 

其中,IndexFunc 的類型參數(shù)沒有使用任何約束(即用的 any),說明查找是通過 f 參數(shù)進行的,它的實現(xiàn)如下:

  1. func IndexFunc[E any](s []E, f func(E) bool) int { 
  2.  
  3. for i, v := range s { 
  4.  
  5. if f(v) { 
  6.  
  7. return i 
  8.  
  9.  
  10.  
  11. return -1 
  12.  

參數(shù) f 是一個函數(shù),它接收一個參數(shù),類型是 E,是一個泛型,和 IndexFunc 的第一個參數(shù)類型 []E 的元素類型保持一致即可,因此可以直接將遍歷 s 的元素傳遞給 f。

修改 slice

一般不建議做相關操作,因為性能較差。如果有較多這樣的需求,可能需要考慮更換數(shù)據(jù)結構。

  1. // 往 slice 的位置 i 處插入元素(可以多個) 
  2. func Insert[S ~[]E, E any](s S, i int, v ...E) S 
  3. // 刪除 slice 中 i 到 j 的元素,即刪除 s[i:j] 元素 
  4. func Delete[S ~[]E, E any](s S, i, j int) S 
  5. // 將連續(xù)相等的元素替換為一個,類似于 Unix 的 uniq 命令。Compact 修改切片的內(nèi)容,它不會創(chuàng)建新切片 
  6. func Compact[S ~[]E, E comparable](s S)  
  7. func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S 
  8. // 增加 slice 的容量,至少增加 n 個 
  9. func Grow[S ~[]E, E any](s S, n int) S 
  10. // 移除沒有使用的容量,相當于縮容 
  11. func Clip[S ~[]E, E any](s S) S 

以上類型約束都包含了兩個:

  • S ~[]E:表明這是一個泛型版 slice,這是對 slice 的約束。注意 [] 前面的 ~,表明支持自定義 slice 類型,如 type myslice []int
  • E any 或 E comparable:對上面 slice 元素類型的約束。

克隆 slice

即獲得 slice 的副本,會進行元素拷貝,注意,slice 中元素的拷貝是淺拷貝,非值類型不會深拷貝。

  1. func Clone[S ~[]E, E any](s S) S { 
  2.  
  3. // Preserve nil in case it matters. 
  4.  
  5. if s == nil { 
  6.  
  7. return nil 
  8.  
  9.  
  10. return append(S([]E{}), s...) 
  11.  

04 總結

因為泛型的存在,同樣的功能,對不同類型的 slice 再也不用寫多份代碼。因為一些功能很常見,因此 Go 官方將其封裝,將來會在標準庫中提供。

出于謹慎考慮,slices 包不會在 1.18 中包含,如果你需要用到 slices 中的功能,可以采用從 slices 代碼中復制的方式,個人覺得依賴 golang.org/x/exp 還是不太好。

slices 源碼地址:https://github.com/golang/exp/blob/master/slices/slices.go。

責任編輯:武曉燕 來源: polarisxu
相關推薦

2023-11-03 14:02:04

Go切片泛型庫

2021-08-09 10:36:20

GoSlices Maps

2021-12-05 23:45:23

Go泛型Maps

2021-09-29 18:17:30

Go泛型語言

2021-12-01 08:29:17

Go泛型Maps

2010-01-06 10:43:49

.NET Framew

2024-10-28 00:40:49

Go語法版本

2022-04-28 12:00:34

Go泛型版排序

2022-03-28 13:34:26

Go泛型部署泛型

2023-11-29 08:19:45

Go泛型缺陷

2023-05-05 08:51:18

Go語言泛型

2021-12-15 10:23:56

Go 1.18 Bet語言泛型

2022-04-15 09:55:59

Go 泛型Go 程序函數(shù)

2022-03-29 11:48:40

Go泛型測試

2021-01-14 05:20:48

Go語言泛型

2021-11-01 12:41:39

Go

2021-12-30 18:34:29

緩存GoSinglefligh

2021-12-28 07:20:44

泛型Go場景

2021-12-13 08:52:42

Go 泛型

2023-09-27 08:26:48

Go標準庫函數(shù)
點贊
收藏

51CTO技術棧公眾號