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

Go 1.22中值得關(guān)注的幾個(gè)變化,你知道幾個(gè)?

開(kāi)發(fā) 前端
記憶中,這似乎是Eli Bendersky首次代表Go團(tuán)隊(duì)撰寫Go版本發(fā)布的文章,文章短小且言簡(jiǎn)意賅,會(huì)讓大家誤以為Go 1.22版本沒(méi)有太多的功能點(diǎn)變更,其實(shí)不然。讀過(guò)我之前寫的“Go 1.22新特性前瞻[4]”一文的童鞋都知道Go 1.22中有很多重要且影響深遠(yuǎn)的值得我們關(guān)注的變化。在這篇文章中,我們就再來(lái)介紹一下這些變化,供大家參考。

美國(guó)時(shí)間2024年2月6日,正當(dāng)中國(guó)人民洋溢在即將迎來(lái)龍年春節(jié)的喜慶祥和的氣氛中時(shí),Eli Bendersky[1]代表Go團(tuán)隊(duì)在Go官博發(fā)文“Go 1.22 is released![2]”,正式向世界宣告了Go 1.22版本的發(fā)布!

圖片

注:大家可以從Go官網(wǎng)下載Go 1.22的第一個(gè)版本go 1.22.0,也可以在Go playground[3]上選擇Go 1.22版本在線體驗(yàn)Go 1.22的語(yǔ)法。

記憶中,這似乎是Eli Bendersky首次代表Go團(tuán)隊(duì)撰寫Go版本發(fā)布的文章,文章短小且言簡(jiǎn)意賅,會(huì)讓大家誤以為Go 1.22版本沒(méi)有太多的功能點(diǎn)變更,其實(shí)不然。讀過(guò)我之前寫的“Go 1.22新特性前瞻[4]”一文的童鞋都知道Go 1.22中有很多重要且影響深遠(yuǎn)的值得我們關(guān)注的變化。在這篇文章中,我們就再來(lái)介紹一下這些變化,供大家參考。

0. 插播“舊聞”:Go再次進(jìn)入Top10,并刷新有史以來(lái)的最高排名

TIOBE編程語(yǔ)言排行榜發(fā)布2024年2月編程語(yǔ)言排名的時(shí)間恰逢中國(guó)人民的傳統(tǒng)佳節(jié)春節(jié)期間,因此它的這次排名發(fā)布“淹沒(méi)”在了“龍年大吉”的喜慶氣氛當(dāng)中了。年后開(kāi)工,大家翻看這條“舊聞”時(shí),才發(fā)現(xiàn)在這次排名中,Go再一次回到Top10,位列第8名,刷新了Go打榜一來(lái)的歷史最好位次。

圖片

單看這一次進(jìn)入top10似乎沒(méi)有什么,因?yàn)?023年4月份,Go也躋身過(guò)top10,排名第10。但如果從Go打榜以來(lái)的歷史曲線來(lái)看,如下圖:

圖片

我們看到了“翹尾”,我們看到了Go邁過(guò)“低谷”后的爬升!這與我在《Go語(yǔ)言第一課專欄》[5]的結(jié)課語(yǔ)《和你一起迎接Go的黃金十年》[6]中預(yù)判:Go即將迎來(lái)自己的黃金十年 愈來(lái)愈吻合了!

不過(guò),我在《2023年Go語(yǔ)言盤點(diǎn):穩(wěn)中求新,穩(wěn)中求變[7]》一文中提到過(guò)TIOBE index作為世界最知名的編程語(yǔ)言排行榜,卻存在其“不靠譜”的特性,比如這一期排名中,上古時(shí)代的編程語(yǔ)言Fortran從去年同期的第24位上升至第11位,僅比PHP落后一位,另一門古老的COBOL語(yǔ)言也從去年同期的第30位上升至第19位,僅僅比大熱的Rust語(yǔ)言落后一位。

因此,對(duì)于TIOBE的排名,大家既要了解,也無(wú)需過(guò)于看重^_^。

言歸正傳,我們來(lái)說(shuō)說(shuō)Go 1.22版本的變化。

1. 語(yǔ)言變化

Go 1.22對(duì)語(yǔ)言語(yǔ)法做了兩處變更,一個(gè)是Go 1.21版本[8]中的試驗(yàn)特性loopvar在Go 1.22中轉(zhuǎn)正落地;另一個(gè)也和for循環(huán)有關(guān),那就是for range新增了對(duì)整型表達(dá)式的支持。兩者相比較,還是第一個(gè)變化loopvar帶來(lái)的影響更大一些。為什么呢?因此這是Go語(yǔ)言發(fā)展歷史上第一次真正的填語(yǔ)義層面的“坑”,而且修改的是一個(gè)在Go源碼中最常用的控制結(jié)構(gòu)的執(zhí)行語(yǔ)義,這很大可能會(huì)帶來(lái)break change。Go101教程[9]的作者老貘[10]將之成為Go歷史上最大的向后兼容性破壞版本[11]。

注:Go 1.21版本[12]有一個(gè)對(duì)panic(nil)的語(yǔ)義修正,但我估計(jì)很少會(huì)有人寫出panic(nil)這樣的代碼。

這次語(yǔ)義修改用一句話表達(dá)就是:將經(jīng)典三段式for循環(huán)語(yǔ)句以及for range語(yǔ)句中的用短聲明形式定義的循環(huán)變量從整個(gè)循環(huán)定義和共享一個(gè),變?yōu)槊總€(gè)迭代定義一個(gè)。

這里借用Go官博文章中那個(gè)例子再說(shuō)明一下這個(gè)語(yǔ)義變化:

// go1.22-examples/lang/loopvar/main.go
package main

import (
 "fmt"
 "time"
)

func main() {
 done := make(chan bool)

 values := []string{"a", "b", "c"}
 for _, v := range values {
  go func() {
   time.Sleep(time.Second)
   fmt.Println(v)
   done <- true
  }()
 }

 // wait for all goroutines to complete before exiting
 for _ = range values {
  <-done
 }
}

我們用Go 1.22.0版本之前的版本,比如Go 1.21.0,來(lái)運(yùn)行該示例:

$go run main.go
c
c
c

我們看到:由于v是整個(gè)循環(huán)中各個(gè)迭代共享的一個(gè)變量,所以在每個(gè)迭代新創(chuàng)建的goroutine中輸出的v都是循環(huán)結(jié)束后v的最終值c。

如果我們用go 1.22.0來(lái)運(yùn)行上述示例,我們將得到:

// 輸出的值的順序與goroutine調(diào)度有關(guān)
$go run main.go
b
c
a

注:關(guān)于Go 1.22版本之前的for range的坑,我的極客時(shí)間專欄《Go語(yǔ)言第一課》[13]專欄有圖文并茂的原理講解,歡迎訂閱閱讀。

那么,loopvar這一語(yǔ)義填“坑”究竟會(huì)對(duì)你的代碼造成怎樣的影響呢?在Russ Cox關(guān)于loopvar語(yǔ)義變更的設(shè)計(jì)文檔[14]中提到了:只有g(shù)o.mod中的go version在go 1.22.0及以后的時(shí)候才會(huì)生效,這是一個(gè)漸進(jìn)式過(guò)渡的過(guò)程,因此目前無(wú)論是開(kāi)源項(xiàng)目還是商業(yè)項(xiàng)目,只要go.mod中的go version還沒(méi)有更新為大于等于go 1.22.0,那么for循環(huán)依然會(huì)保留短聲明定義的變量的原語(yǔ)義,這樣這些項(xiàng)目都不會(huì)受到影響。

不過(guò),如果是直接在腳本中通過(guò)go run xxx.go形式運(yùn)行某個(gè)go源碼的,且當(dāng)前工作目錄以及父目錄下沒(méi)有g(shù)o.mod文件的,go 1.22.0會(huì)采用新的loopvar語(yǔ)義,這點(diǎn)大家要注意了。

此外,當(dāng)你將go.mod中的go version升級(jí)到go 1.22.0或更高版本時(shí),也要注意語(yǔ)義變更可能帶來(lái)的問(wèn)題。在升級(jí)go version之前,可以用Go 1.22版本之前的go vet對(duì)項(xiàng)目源碼進(jìn)行一次靜態(tài)分析,對(duì)于go vet提示:“l(fā)oop variable v captured by func literal”的地方務(wù)必注意逐個(gè)確認(rèn)。

注:Go 1.22版本中的go vet已經(jīng)移除了在go version >= 1.22.0時(shí),對(duì)“l(fā)oop variable v captured by func literal”情況進(jìn)行警告的功能。

關(guān)于Go 1.22中for range支持后面接整型表達(dá)式的“語(yǔ)法糖”新特性以及函數(shù)迭代器的實(shí)驗(yàn)特性[15],這里就不細(xì)說(shuō)了,大家可以看看“Go 1.22新特性前瞻[16]”一文中的說(shuō)明。

2. 編譯器、運(yùn)行時(shí)與工具鏈

在編譯器、運(yùn)行時(shí)和工具鏈這些方面,Go 1.22的正式版本與“Go 1.22新特性前瞻[17]”一文中使用的Go 1.22rc1版本幾乎沒(méi)有差異,這里挑主要內(nèi)容介紹一下,其他一些內(nèi)容可以參考前瞻[18]一文。

Go 1.22版本繼續(xù)在編譯上優(yōu)化PGO(profile-guided optimization), 基于PGO的構(gòu)建可以比以前版本實(shí)現(xiàn)更高比例的調(diào)用去虛擬化(devirtualize)。在Go 1.22中,官?給出的PGO帶來(lái)的性能提升數(shù)字是2%~14%,這應(yīng)該是基于Google內(nèi)部一些典型的Go程序測(cè)算出來(lái)的。

注:如果你對(duì)PGO優(yōu)化還不是很了解,可以看看“深入理解Profile Guided Optimization(PGO)[19]”這篇文章。

Go 1.22版本編譯器現(xiàn)在可以更多運(yùn)?devirtualize和inline。在Go編譯器中,devirtualize是一種編譯優(yōu)化技術(shù),旨在消除“虛函數(shù)”調(diào)用的開(kāi)銷。“虛函數(shù)”是指在面向?qū)ο缶幊讨?,通過(guò)基類指針或引用調(diào)用的函數(shù)。在Go中所謂虛函數(shù)調(diào)用指的就是通過(guò)接口類型變量進(jìn)行的方法調(diào)用。由于是動(dòng)態(tài)調(diào)用,基于接口的方法調(diào)用需要在運(yùn)行時(shí)進(jìn)行查找和分派,這可能導(dǎo)致一定的性能損失。

而Go編譯器在進(jìn)行devirtualize優(yōu)化時(shí),會(huì)嘗試根據(jù)程序的上下文信息和類型信息,確定方法調(diào)用的具體對(duì)象實(shí)例。如果編譯器能夠確定調(diào)用的具體實(shí)例,則會(huì)將通過(guò)接口的方法調(diào)用替換為直接調(diào)用具體對(duì)象實(shí)例的方法,從而消除運(yùn)行時(shí)的開(kāi)銷,使得通過(guò)接口類型變量進(jìn)行方法調(diào)用的性能得到優(yōu)化提升。

Go 1.22版本中的運(yùn)行時(shí)可以使基于類型的垃圾收集的元數(shù)據(jù)更接近每個(gè)堆對(duì)象,從而將Go程序的CPU性能(延遲或吞吐量)提高了1-3%。這一變化還支持通過(guò)重復(fù)數(shù)據(jù)刪除冗余元數(shù)據(jù),進(jìn)而將大多數(shù)Go程序的內(nèi)存開(kāi)銷減少了大約1%。

在工具鏈方面,有三個(gè)主要改變這里提一下:

  • go work支持vendor

在Go 1.22版本中,通過(guò)go work vendor可以將workspace中的依賴放到vendor?錄下,同時(shí)在構(gòu)建時(shí),如果workspace下有vendor?錄,那么默認(rèn)的構(gòu)建是go build -mod=vendor,即基于vendor的構(gòu)建。

  • go mod init不再care其他vendor工具的配置文件

go mod init不再嘗試將其他vendor工具(例如Gopkg.lock )的配置文件導(dǎo)入到go module依賴文件(go.mod)中了,也就是說(shuō)從Go 1.22版本開(kāi)始,go module出現(xiàn)之前的那些gopath時(shí)代的依賴管理工具正式退出并成為歷史了。

  • 改進(jìn)go test -cover的輸出

對(duì)于沒(méi)有自己的測(cè)試文件的包,go test -cover在go 1.22版本之前會(huì)輸出:

? mymod/mypack [no test files]

但在Go 1.22版本之后,會(huì)報(bào)告覆蓋率為0.0%:

mymod/mypack coverage: 0.0% of statements

3. 標(biāo)準(zhǔn)庫(kù)

這里列舉一下標(biāo)準(zhǔn)庫(kù)值得關(guān)注的重大變化,大家可以與前瞻[20]一文相互參考著閱讀。

3.1 math/rand/v2:標(biāo)準(zhǔn)庫(kù)的第一個(gè)v2版本包

Go 1.22中新增了math/rand/v2包,這里之所以將它列為Go 1.22版本標(biāo)準(zhǔn)庫(kù)的?次重要變化,是因?yàn)檫@是標(biāo)準(zhǔn)庫(kù)第一次為某個(gè)包建?v2版本,按照Russ Cox的說(shuō)法,這次math/rand/v2包的創(chuàng)建,算是為標(biāo)準(zhǔn)庫(kù)中的其他可能的v2包“探探路”,找找落地路徑。關(guān)于math/rand/v2包相對(duì)于原math/rand包的變化有很多,具體可以參考issue 61716[21]中的設(shè)計(jì)與討論。

3.2 增強(qiáng)http.ServeMux表達(dá)能力

在Go 1.22版本中,http.ServeMux的表達(dá)能力得到了大幅提升,從原先只支持靜態(tài)路由,到新版本中支持如下一些特性:

  • "/index.html"路由將匹配任何主機(jī)和方法的路徑"/index.html";
  • "GET /static/"將匹配路徑以"/static/"開(kāi)頭的GET請(qǐng)求;
  • "example.com/"可以與任何指向主機(jī)為"example.com"的請(qǐng)求匹配;
  • "example.com/{$}"會(huì)匹配主機(jī)為"example.com"、路徑為"/"的請(qǐng)求,即"example.com/";
  • "/b/{bucket}/o/{objectname...}"匹配第一段為"b"、第三段為"o"的路徑。名稱"bucket"表示第二段,"objectname"表示路徑的其余部分。

并且新版ServeMux在路由匹配性能方面也不輸眾多開(kāi)源http路由框架太多,后續(xù)建立Go web或api類新項(xiàng)目時(shí),可以考慮首選新版ServeMux來(lái)進(jìn)行路由匹配了,減少對(duì)外部的一個(gè)依賴。

關(guān)于新版http.ServeMux的具體使用方法,其作者Jonathan Amsterdam(也是log/slog[22]的作者)在官博發(fā)表了一篇名為“Routing Enhancements for Go 1.22[23]”的文章,大家可以詳細(xì)參考。

關(guān)于標(biāo)準(zhǔn)庫(kù)的其他一些變化,大家可以參考前瞻[24]一文以及更詳細(xì)的Go 1.22的發(fā)布說(shuō)明文檔[25]

4. 小結(jié)

綜上,Go 1.22版本對(duì)語(yǔ)言、編譯器、工具鏈、運(yùn)行時(shí)和標(biāo)準(zhǔn)庫(kù)都有一定程度的改進(jìn)和創(chuàng)新,遺留代碼通過(guò)Go 1.22版本的重新編譯便可以得到一定程度的性能上的自然提升,這也體現(xiàn)了Go語(yǔ)言在穩(wěn)中求新、穩(wěn)中求變[26]的特點(diǎn)。

不過(guò)這里還要提醒各位Go開(kāi)發(fā)者,在升級(jí)Go 1.22版本時(shí)務(wù)必注意潛在的向后兼容性問(wèn)題,尤其是loopvar語(yǔ)義帶來(lái)的變化影響。

本文涉及的源碼可以在這里[27]下載。

參考資料

[1] 

Eli Bendersky: https://github.com/eliben

[2] Go 1.22 is released!: https://go.dev/blog/go1.22

[3] Go playground: https://go.dev/play/

[4] Go 1.22新特性前瞻: https://tonybai.com/2023/12/25/go-1-22-foresight/

[5] 《Go語(yǔ)言第一課專欄》: http://gk.link/a/10AVZ

[6] 《和你一起迎接Go的黃金十年》: https://time.geekbang.org/column/article/486536

[7] 2023年Go語(yǔ)言盤點(diǎn):穩(wěn)中求新,穩(wěn)中求變: https://tonybai.com/2023/12/31/the-2023-review-of-go-programming-language/

[8] Go 1.21版本: https://tonybai.com/2023/08/20/some-changes-in-go-1-21/

[9] Go101教程: https://go101.org/

[10] 老貘: https://github.com/go101

[11] Go歷史上最大的向后兼容性破壞版本: https://twitter.com/go100and1/status/1755598141351677983

[12] Go 1.21版本: https://tonybai.com/2023/08/20/some-changes-in-go-1-21/

[13] 《Go語(yǔ)言第一課》: http://gk.link/a/10AVZ

[14] 關(guān)于loopvar語(yǔ)義變更的設(shè)計(jì)文檔: https://go.googlesource.com/proposal/+/master/design/60078-loopvar.md

[15] 函數(shù)迭代器的實(shí)驗(yàn)特性: https://go.dev/wiki/RangefuncExperiment

[16] Go 1.22新特性前瞻: https://tonybai.com/2023/12/25/go-1-22-foresight/

[17] Go 1.22新特性前瞻: https://tonybai.com/2023/12/25/go-1-22-foresight/

[18] 前瞻: https://tonybai.com/2023/12/25/go-1-22-foresight

[19] 深入理解Profile Guided Optimization(PGO): https://andrewwphillips.github.io/blog/pgo.html

[20] 前瞻: https://tonybai.com/2023/12/25/go-1-22-foresight

[21] issue 61716: https://go.dev/issue/61716

[22] log/slog: https://tonybai.com/2022/10/30/first-exploration-of-slog

[23] Routing Enhancements for Go 1.22: https://go.dev/blog/routing-enhancements

[24] 前瞻: https://tonybai.com/2023/12/25/go-1-22-foresight

[25] Go 1.22的發(fā)布說(shuō)明文檔: https://go.dev/doc/go1.22

[26] Go語(yǔ)言在穩(wěn)中求新、穩(wěn)中求變: https://tonybai.com/2023/12/31/the-2023-review-of-go-programming-language

[27] 這里: https://github.com/bigwhite/experiments/tree/master/go1.22-examples

[28] Gopher部落知識(shí)星球: https://public.zsxq.com/groups/51284458844544

[29] 鏈接地址: https://m.do.co/c/bff6eed92687

責(zé)任編輯:武曉燕 來(lái)源: TonyBai
相關(guān)推薦

2023-03-07 11:23:04

2022-01-10 11:33:17

Go測(cè)試軟件

2011-08-19 09:41:56

C++

2025-03-25 10:49:13

2022-04-13 10:05:48

網(wǎng)關(guān)Flowable事件訂閱

2015-03-09 15:51:47

WEB技術(shù)WEB 2015年

2021-11-04 11:54:30

Linux內(nèi)存系統(tǒng)

2024-11-18 00:18:18

2022-07-18 08:08:16

Go?語(yǔ)言技巧

2024-05-09 10:28:46

容器ListElement?

2024-08-06 11:40:57

2024-03-01 13:48:00

Git配置系統(tǒng)

2013-06-27 14:57:58

Eclipse超酷插件移動(dòng)開(kāi)發(fā)

2023-04-27 08:15:09

2021-02-27 17:13:21

前端代碼邏輯

2021-10-12 09:20:02

數(shù)據(jù)庫(kù)SQL腳本

2024-01-18 00:16:07

2022-04-06 07:32:41

Java運(yùn)算符變量

2024-10-28 13:18:54

2024-09-05 14:50:31

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)