大家好,我是煎鱼。
最近介绍了 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 新版本的新方法、函数,目前来看这些函数没有特别大的功能调整,主要都是对于日常工程开发上的优化。
这些新调整也算是针对开发效率的一定的提效了,大家可以及时用到工作的开发上!