深入探索Go?1.21中的?maps工具庫
前言
隨著 Go 1.21.0
版本的發(fā)布,新增了兩個實(shí)用的泛型工具庫:maps
和 slices
,它們分別提供了處理映射(map
)和切片常見操作的函數(shù),減少了我們重復(fù)造輪子的過程,提高開發(fā)效率。本文將會對 maps
工具庫進(jìn)行介紹。
準(zhǔn)備好了嗎?準(zhǔn)備一杯你最喜歡的咖啡或茶,隨著本文一探究竟吧。
Maps
maps
是一個泛型工具庫,該庫包含了對任何類型都支持的實(shí)用函數(shù),函數(shù)簡介如下表所示:
函數(shù) | 函數(shù)簽名 | 功能 |
---|---|---|
Clone | func Clone[M ~map[K]V, K comparable, V any](m M) M | 該函數(shù)返回 m 的一個副本,底層基于淺層克隆去實(shí)現(xiàn),使用普通賦值的方式去設(shè)置新的鍵值對 |
Copy | func Copy[M1 ~map[K]V, M2 ~map[K]V, K comparable, V any](dst M1, src M2) | 復(fù)制 src 中的所有鍵值對到 dst 中,如果 dst 中包含 src 中的任意 key,則該 key 對應(yīng)的 value 將會被覆蓋 |
DeleteFunc | func DeleteFunc[M ~map[K]V, K comparable, V any](m M, del func(K, V) bool) | 刪除 m 中滿足 del 返回為 true 的任何鍵值對 |
Equal | func Equal[M1, M2 ~map[K]V, K, V comparable](m1 M1, m2 M2) bool | 判斷兩個 map 是否包含相同的鍵值對,內(nèi)部使用 == 進(jìn)行比較 |
EqualFunc | func EqualFunc[M1 ~map[K]V1, M2 ~map[K]V2, K comparable, V1, V2 any](m1 M1, m2 M2, eq func(V1, V2) bool) bool | 類似 Equal 函數(shù),但通過 eq 函數(shù)進(jìn)行比較值,鍵仍使用 == 進(jìn)行比較 |
Clone
Clone
函數(shù)接收一個 m
參數(shù),該函數(shù)的功能是返回 m
的副本,底層基于淺層克隆去實(shí)現(xiàn),使用普通賦值的方式去設(shè)置新的鍵值對。
代碼示例:
package main import ( "fmt" "maps" ) func main() { type Programmer struct { Name string City string } m1 := map[string]Programmer{ "programmer-01": {Name: "陳明勇", City: "深圳"}, "programmer-02": {Name: "張三", City: "廣州"}, } m2 := maps.Clone(m1) fmt.Printf("m1: %v\n", m1) fmt.Printf("m2: %v\n", m2) }
執(zhí)行結(jié)果:
m1: map[programmer-01:{陳明勇 深圳} programmer-02:{張三 廣州}]
m2: map[programmer-01:{陳明勇 深圳} programmer-02:{張三 廣州}]
上述例子中,首先創(chuàng)建一個 map
類型的變量 m1
,然后通過 maps.Clone()
函數(shù)進(jìn)行克隆,得到 m2
,最后通過打印結(jié)果可知 m2
的值和 m1
的值一樣。
從函數(shù)的功能描述中可知,Clone
函數(shù)的原理是淺層克隆,那么修改克隆后的 map
任意 key
的 value
將有可能影響原 map
的 value
。
我們來看下下面的例子:
package main import ( "fmt" "maps" ) func main() { type Programmer struct { Name string City string } m1 := map[string]*Programmer{ "programmer-01": {Name: "陳明勇", City: "深圳"}, "programmer-02": {Name: "張三", City: "廣州"}, } fmt.Printf("m1: %v, %v\n", *m1["programmer-01"], *m1["programmer-02"]) m2 := maps.Clone(m1) fmt.Printf("m2: %v, %v\n", *m2["programmer-01"], *m2["programmer-02"]) m2["programmer-02"].City = "??? fmt.Printf("m2 被修改后,m1: %v, %v\n", *m1["programmer-01"], *m1["programmer-02"]) fmt.Printf("m2 被修改后,m2: %v, %v\n", *m2["programmer-01"], *m2["programmer-02"]) }
執(zhí)行結(jié)果
m1: {陳明勇 深圳}, {張三 廣州}
m2: {陳明勇 深圳}, {張三 廣州}
m2 被修改后,m1: {陳明勇 深圳}, {張三 海口}
m2 被修改后,m2: {陳明勇 深圳}, {張三 海口}
與前面的示例不同,這個例子中的一個關(guān)鍵區(qū)別在于 value
是指針類型。從執(zhí)行結(jié)果可以明顯看出,如果 m1
的 value
是指針類型,那么在對克隆后的 m2
中的任意 key
對應(yīng)的 value
進(jìn)行修改操作后,都會直接影響到 m1
。這是因為 m1
和 m2
共享了同一組指向相同 Programmer
結(jié)構(gòu)體的指針,因此對一個指針的修改會在兩個 map
中都可見。
Copy
Copy
函數(shù)接收兩個 map
參數(shù) dst
和 src
,該函數(shù)的功能是復(fù)制 src
中的所有鍵值對到 dst
中,如果 dst
中包含 src
中的任意 key
,則該 key
對應(yīng)的 value
將會被覆蓋。
代碼示例:
package main import ( "fmt" "maps" ) func main() { m1 := map[string]string{"Name": "陳明勇", "City": "深圳"} m2 := map[string]string{"City": "廣州", "Phone": "123456789"} maps.Copy(m1, m2) fmt.Println(m1) }
執(zhí)行結(jié)果:
map[City:廣州 Name:陳明勇 Phone:123456789]
在上述例子中,首先創(chuàng)建了兩個 map
變量,分別為 m1
和 m2
,然后通過 maps.Copy
函數(shù),將 m2
中的鍵值對復(fù)制到 m1
中,最后打印復(fù)制后的結(jié)果。
根據(jù)結(jié)果可知,由于 m1
和 m2
都包含 key → City
,因此在執(zhí)行復(fù)制操作后, m1
中的 key → City
對應(yīng)的 value
值會被覆蓋。
DeleteFunc
DeleteFunc
函數(shù)接收一個 map
類型的參數(shù) m
和一個函數(shù)類型的參數(shù) del
。該函數(shù)的功能是刪除 m
中滿足 del
返回為 true
的任何鍵值對。
代碼示例:
package main import ( "fmt" "maps" ) func main() { m1 := map[int]string{1: "陳明勇", 2: "張三", 3: "李四", 4: "王五"} maps.DeleteFunc(m1, func(k int, v string) bool { return k%2 == 0 }) fmt.Println(m1) }
執(zhí)行結(jié)果:
map[1:陳明勇 3:李四]
在上述例子中,首先創(chuàng)建了一個 map
變量 m1
,使用 int
類型作為學(xué)號(key
),string
類型作為姓名(value
),然后通過 maps.DeleteFunc
刪除學(xué)號為雙數(shù)的學(xué)生,匿名函數(shù)的邏輯是 當(dāng)學(xué)號為雙數(shù)時,返回 true。
總體來說這個例子相對簡單,讀者可根據(jù)實(shí)際應(yīng)用場景進(jìn)行使用 DeleteFunc
函數(shù)。
Equal
Equal
函數(shù)接收兩個 map
變量,函數(shù)的返回值為 bool
類型。該函數(shù)的功能是判斷兩個 map
是否包含相同的鍵值對,內(nèi)部使用 ==
進(jìn)行比較。注意:map
類型的 key
和 value
必須是 comparable
類型。
代碼示例:
package main import ( "fmt" "maps" ) func main() { m1 := map[int]int{0: 0, 1: 1, 2: 2} m2 := map[int]int{0: 0, 1: 1} m3 := map[int]int{0: 0, 1: 1, 2: 2} fmt.Println(maps.Equal(m1, m2)) // false fmt.Println(maps.Equal(m1, m3)) // true }
執(zhí)行結(jié)果:
false
true
上述例子中,首先創(chuàng)建了三個 map
類型變量,分別是 m1
、m2
和 m3
,然后通過 maps.Equal()
函數(shù),對 m1
和 m2
以及 m1
和 m3
進(jìn)行等價比較。執(zhí)行結(jié)果與預(yù)期一致,m1
和 m3
是相等的,m1
和 m2
不相等。
EqualFunc
EqualFunc
函數(shù)類似 Equal
函數(shù),只不過是通過 eq
函數(shù)進(jìn)行比較值,鍵仍使用 ==
進(jìn)行比較。注意: value
可以為任意類型(any
)。
代碼示例:
package main import ( "fmt" "maps" ) func main() { type User struct { Nickname string IdCard string } m1 := map[int]User{0: {Nickname: "陳明勇", IdCard: "111"}, 1: {Nickname: "張三", IdCard: "222"}} m2 := map[int]User{0: {Nickname: "陳明勇", IdCard: "111"}} m3 := map[int]User{0: {Nickname: "Go技術(shù)干貨", IdCard: "111"}, 1: {Nickname: "張三", IdCard: "222"}} fmt.Println(maps.EqualFunc(m1, m2, func(user User, user2 User) bool { return user.IdCard == user2.IdCard })) // false fmt.Println(maps.EqualFunc(m1, m3, func(user User, user2 User) bool { return user.IdCard == user2.IdCard })) // true }
執(zhí)行結(jié)果:
false
true
上述例子中,首先創(chuàng)建了三個 map
類型變量,分別是 m1
、m2
和 m3
。這些 map
使用 int
類型作為編號(key
),User
類型作為用戶信息(value
)。
接著,使用 maps.EqualFunc()
函數(shù),對 m1
和 m2
以及 m1
和 m3
進(jìn)行等價比較,在這個函數(shù)中,我們自定義了比較函數(shù) eq
,其邏輯是只要兩個 User
結(jié)構(gòu)體的 IdCard
相同,就認(rèn)為它們是同一個人(相等)。執(zhí)行結(jié)果與預(yù)期一致,m1
和 m3
是相等的,m1
和 m2
不相等。
小結(jié)
本文對 Go
工具庫 maps
進(jìn)行詳細(xì)介紹,包括其提供的函數(shù) Clone
、Copy
、DeleteFunc
、Equal
和 EqualFunc
,并強(qiáng)調(diào)了使用這些函數(shù)時需要注意的地方。
總的來說,通過使用這些函數(shù),減少了我們重復(fù)造輪子的過程,提高開發(fā)效率。
你使用 maps
工具庫了嗎?
推薦閱讀
Go 1.21新內(nèi)置函數(shù)min、max和clear的用法詳解
到此這篇關(guān)于深入探索Go 1.21中的 maps工具庫的文章就介紹到這了,更多相關(guān)Go 1.21 maps內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go語言fmt.Sprintf格式化輸出的語法與實(shí)例
Go 可以使用 fmt.Sprintf 來格式化字符串,下面這篇文章主要給大家介紹了關(guān)于Go語言fmt.Sprintf格式化輸出的語法與實(shí)例,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-07-07golang封裝一個執(zhí)行命令行的函數(shù)(return?stderr/stdout/exitcode)示例代碼
在?Go?語言中,您可以使用?os/exec?包來執(zhí)行外部命令,不通過調(diào)用?shell,并且能夠獲得進(jìn)程的退出碼、標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯誤輸出,下面給大家分享golang封裝一個執(zhí)行命令行的函數(shù)(return?stderr/stdout/exitcode)的方法,感興趣的朋友跟隨小編一起看看吧2024-06-06Go 語言json.Unmarshal 遇到的小問題(推薦)
這篇文章主要介紹了 Go 語言json.Unmarshal 遇到的小問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-07-07