Go1.21 速覽:新內(nèi)置函數(shù) Clear、Min、Max 和新標(biāo)準(zhǔn)庫(kù)包 Cmp!
大家好,我是煎魚。
前面給大家分享了 Go1.21 正式不支持 macOS 10.13 和 10.14 的支持。嚇得我趕緊把我的 2017 款的老爺機(jī)從 10.14 升成 13.4。感覺(jué) mbp 已經(jīng)變成了暖寶寶。??
今天給大家分享的是 Go 1.21 中的兩個(gè)雙新增項(xiàng),分別是新的 3 個(gè)內(nèi)置方法和新的標(biāo)準(zhǔn)庫(kù)包。
新內(nèi)置函數(shù)
本次新版本新增的內(nèi)置函數(shù)分別是:clear、min、max,面向不同的場(chǎng)景,函數(shù)名和函數(shù)作用一致,不得不說(shuō)論命名的藝術(shù)。
我們一個(gè)個(gè)來(lái)展開介紹。
clear 函數(shù)
引入背景
這個(gè) clear 內(nèi)置函數(shù)的加入,真的是等的夠久了。在 2022 年的《Go 大佬良心發(fā)現(xiàn),愿意給 map 加清除了?》的文章中,我們有介紹過(guò)。
簡(jiǎn)單來(lái)講,有如下兩個(gè)問(wèn)題:
- Go 一直以來(lái)大家就在吵要清空 map 等類型的內(nèi)容物。需要 for-range + delete 來(lái)清空,略繁瑣。
- 有一類神奇的值,叫做:NaN(Not a Number,非數(shù))。它是數(shù)值數(shù)據(jù)類型的一類值,表示未定義或不可表示的值。有開發(fā)者發(fā)現(xiàn)無(wú)法清空 NaN 的值。有 BUG。
扯到今年吵來(lái)吵去,擴(kuò)大了原有的范圍。
函數(shù)作用
最終 Go1.21 新加入的內(nèi)置函數(shù) clear 接受 map、slice、指向數(shù)組的指針或類型參數(shù)類型的參數(shù)。
函數(shù)簽名如下:
func clear[T ~[]Type | ~map[Type]Type1](t T)
分別有如下的作用:
- 對(duì)于 map,會(huì)刪除所有條目(包含前面提到的 NaN),將會(huì)變成一個(gè)空 map。len 屬性的值會(huì)改變,值為 0 。
- 對(duì)于 slice,會(huì)將 slice 或 array 長(zhǎng)度內(nèi)的所有元素設(shè)置為相應(yīng)元素類型的零值。len 屬性的值不會(huì)改變。
- 對(duì)于泛型的類型參數(shù)(type parameter):類型參數(shù)的類型集必須只包含 map、slices 或指向數(shù)組的指針的類型,clear 函數(shù)將會(huì)執(zhí)行實(shí)際類型參數(shù)所對(duì)應(yīng)的 clear 操作。
演示代碼
map 演示代碼如下:
func main() {
m := map[string]string{"腦子進(jìn)": "煎魚了", "煎魚": "進(jìn)腦子了"}
fmt.Printf("m1: %v, len: %d\n", m, len(m))
clear(m)
fmt.Printf("m2: %v, len: %d\n", m, len(m))
}
輸出結(jié)果:
m1: map[煎魚:進(jìn)腦子了 腦子進(jìn):煎魚了], len: 2
m2: map[], len: 0
slice 演示代碼如下:
func main() {
s := make([]string, 3)
s[0] = "吃"
s[1] = "煎"
s[2] = "魚"
fmt.Printf("s1: %v, len: %d, cap:%d\n", s, len(s), cap(s))
clear(s)
fmt.Printf("s2: %v, len: %d, cap:%d\n", s, len(s), cap(s))
}
輸出結(jié)果:
s1: [吃 煎 魚], len: 3, cap:3
s2: [ ], len: 3, cap:3
min、max 函數(shù)
這兩個(gè)函數(shù)的誕生主要是 @Ian Lance Taylor 發(fā)現(xiàn) min、max 函數(shù)。作用是求最小值和最大值。雖然在功能上很微小。但是在代碼中卻被廣泛使用了,認(rèn)為值得引入標(biāo)準(zhǔn)庫(kù)中。
隨后被 @Robert Griesemer 往內(nèi)置函數(shù)引導(dǎo),基于 append 和 copy 內(nèi)置函數(shù)的先例,就獲得許多人的點(diǎn)贊認(rèn)可該觀點(diǎn),就正式加入內(nèi)置函數(shù)了。
官方給出的演示代碼如下:
var x, y int
m := min(x) // m == x
m := min(x, y) // m 是 x 和 y 中較小的那個(gè)
m := max(x, y, 10) // m 是 x 和 y 中較大的一個(gè),但至少是10
c := max(1, 2.0, 10) // c == 10.0(浮點(diǎn)類型)
f := max(0, float32(x)) // f 的類型是 float32
var s []string
_ = min(s...) // 無(wú)效:不允許使用 slice 參數(shù)
t := max("", "foo", "bar") // t == "foo" (string 類型)
對(duì)于一些特殊值和清空,例如:浮點(diǎn)參數(shù)、負(fù)零、NaN和無(wú)窮大。min、max 函數(shù)結(jié)果適用以下規(guī)則:
x y min(x, y) max(x, y)
-0.0 0.0 -0.0 0.0
-Inf y -Inf y
+Inf y y +Inf
NaN y NaN NaN
- 第一行:負(fù)零比(非負(fù))零小。
- 第二行:負(fù)無(wú)窮大比任何其他數(shù)字都小。
- 第三行:正無(wú)窮大于任何其他數(shù)字。
- 第四行:如果有任何一個(gè)參數(shù)是 NaN,結(jié)果就是 NaN。
新標(biāo)準(zhǔn)庫(kù)包
本次在標(biāo)準(zhǔn)庫(kù)中新增的包是 cmp(全稱應(yīng)該是 compare),主要是提供比較、對(duì)比等功能。
這塊比較簡(jiǎn)單,直接上源碼就懂了:
package cmp
type Ordered interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
~float32 | ~float64 |
~string
}
func Less[T Ordered](x, y T) bool {
return (isNaN(x) && !isNaN(y)) || x < y
}
func Compare[T Ordered](x, y T) int {
xNaN := isNaN(x)
yNaN := isNaN(y)
if xNaN && yNaN {
return 0
}
if xNaN || x < y {
return -1
}
if yNaN || x > y {
return +1
}
return 0
}
func isNaN[T Ordered](x T) bool {
return x != x
}
- Less:判斷 x 是否小于 y。對(duì)于浮點(diǎn)類型,NaN 被認(rèn)為小于任何非 NaN、 而 -0.0 不小于(等于)0.0。
- Compare:比較 x 和 y,返回對(duì)應(yīng)預(yù)定義的枚舉值:
如果 x 小于 y,則返回 -1
如果 x 等于 y,則返回 0
如果 x 大于 y,則返回 +1
- isNaN:判斷 x 是否為 NaN。
前面提到的 min、max 內(nèi)置函數(shù),本來(lái)也是要放在 cmp 包里的,不過(guò)非常榮幸的被 “提拔” 了。僅留下這幾個(gè)方法。
總結(jié)
今天給大家分享了 Go1.21 的一些新內(nèi)置函數(shù) clear、min、max 和新標(biāo)準(zhǔn)庫(kù)包 cmp。雖然看起來(lái)都是輔助類工具,但他們的加入也是挺費(fèi)勁的,花了不少時(shí)間和討論。
以后寫業(yè)務(wù)代碼和八股文時(shí),可以適當(dāng)使用這些函數(shù)。又能夠簡(jiǎn)化部分代碼和邏輯了。