Go1.23 新特性:Slices、Panic、Cookie 等函數改進,效率提高了!
大家好,我是煎魚。
最近介紹了 Go1.23 的幾個重要新特性。今天給大家分享一些本次新版本的方法/函數的功能優化、改進的匯總。
主打一個快速知悉,跟上新用法。看看 rsc 在 Go 核心團隊負責人的職業生涯最后都推動了什么函數的合入。
Go1.23 方法/函數優化
slices.Repeat
這是一個今年(2024 年)才提出的新提案,原提案作者提供給功能介紹時,還給出了其他語言的相關案例。很快受到了 Go 官方團隊的響應并通過。
圖片
函數簽名:
func Repeat[S ~[]E, E any](x S, count int "S ~[]E, E any") S
Repeat 方法會返回一個新的切片,函數的作用是將所提供的切片,按給定的次數進行重復。
注意:如果 count 為負數或溢出,該方法會觸發 panic 事件。
Go1.23 代碼例子如下:
import (
"fmt"
"slices"
)
func main() {
s := []string{"煎魚", "咸魚", "摸魚"}
repeat := slices.Repeat(s, 2)
fmt.Println(repeat)
}
輸出結果:
[煎魚 咸魚 摸魚 煎魚 咸魚 摸魚]
os.DirFS
這個新提案由 rsc 于 2023 年從 2021 年的舊提案轉化過來,目的上是為了更安全地將目標文件復制到本地文件系統,認為可以幫助到很多場景。
圖片
函數簽名:
func DirFS(dir string) fs.FS
os.DirFS 方法返回以目錄 dir 為根的文件樹的文件系統(fs.FS),再結合 os.CopyFS 方法可以實現一次性的遞歸復制文件和目錄。
Go1.23 代碼例子如下:
src := os.DirFS("/Users/eddycjy/hello.txt")
dst := "/tmp/hello.txt"
err := os.CopyFS(dst, src)
if err != nil {
panic(err)
}
fmt.Printf("copied %s to %s\n", src, dst)
panic
在 Go1.22 及以前的版本,運行以下代碼:
func main() {
panic("腦子\n進\nI\n煎魚了")
}
輸出結果如下:
panic: 腦子
進
I
煎魚了
goroutine 1 [running]:
main.main()
/tmp/sandbox3096848362/prog.go:6 +0x25
Go1.23 新版本起,輸出結果將會變成:
panic: 腦子
進
I
煎魚了
goroutine 1 [running]:
main.main()
/tmp/sandbox1717599036/prog.go:6 +0x25
新版本后,panic 函數會用制表符縮進錯誤信息(如 panic 的參數)的第二行和后續行,以區別于第一個 goroutine 的堆棧跟蹤。
http.ParseCookie/ParseSetCookie
現在在 Go 程序中,如果我們要從 cookie 標頭字符串中提取 cookie 結構體。需要編寫以下類似的代碼:
req := http.Request{Header: http.Header{"Cookie": []string{raw}}}
cookies := req.Cookies()
雖然從原提案的角度來看還能用。但是終究繞了幾層才把東西取到,也不方便。
因此 @Eyal Posener 在 2018 年提出了 x/net/http/httpguts: add ParseCookie and ParseSetCookie[1] 的新提案訴求。在 2024 年,rsc 重新把這活拎了出來,加進了新版本中。
本次 Go1.23 是在 net.http 標準庫中新增了如下兩個方法:
- ParseCookie
- ParseSetCookie
ParseCookie
函數簽名:
func ParseCookie(line string) ([]*Cookie, error)
ParseCookie 解析 Cookie 標頭值并返回其中設置的所有 Cookie。
Go1.23 代碼例子如下:
func main() {
lines := "session_id=eddycjy; value=hello-world; lang=en; lang=zh-CN"
cookies, _ := http.ParseCookie(lines)
for _, cookie := range cookies {
fmt.Printf("%s: %s\n", cookie.Name, cookie.Value)
}
}
輸出結果:
session_id: eddycjy
value: hello-world
lang: en
lang: zh-CN
如果存在多個相同字段,將會返回多次。
ParseSetCookie
函數簽名:
func ParseSetCookie(line string) (*Cookie, error)
ParseSetCookie 函數解析 Set-Cookie 標頭值并返回 Cookie。
Go1.23 代碼例子如下:
func main() {
line := "session_id=eddycjy; MaxAge=0; lang=zh-CN; Domain=.eddycjy.com"
cookie, _ := http.ParseSetCookie(line)
fmt.Println("Name:", cookie.Name)
fmt.Println("Value:", cookie.Value)
fmt.Println("Domain:", cookie.Domain)
fmt.Println("MaxAge:", cookie.MaxAge)
}
輸出結果:
Name: session_id
Value: eddycjy
Domain: .eddycjy.com
MaxAge: 0
在解析結果上,主要是對標 Cookie,有預定義的標準字段:
type Cookie struct {
Name string
Value string
Path string // optional
Domain string // optional
Expires time.Time // optional
RawExpires string // for reading cookies only
// MaxAge=0 means no 'Max-Age' attribute specified.
// MaxAge<0 means delete cookie now, equivalently 'Max-Age: 0'
// MaxAge>0 means Max-Age attribute present and given in seconds
MaxAge int
Secure bool
HttpOnly bool
SameSite SameSite
Raw string
Unparsed []string // Raw text of unparsed attribute-value pairs
}
如果有自定義字段需要讀取的,可以使用 Cookie.Raw 讀取到原始的字符串進行解析和額外處理。
總結
今天給大家分享了一些 Go1.23 新版本的新方法、函數,目前來看這些函數沒有特別大的功能調整,主要都是對于日常工程開發上的優化。
這些新調整也算是針對開發效率的一定的提效了,大家可以及時用到工作的開發上!