Go1.23 新特性:slices、panic、cookie 等函数改进,效率提高了!

大家好,我是煎鱼。

最近介绍了 Go1.23 的几个重要新特性。今天给大家分享一些本次新版本的方法/函数的功能优化、改进的汇总。

主打一个快速知悉,跟上新用法。看看 rsc 在 Go 核心团队负责人的职业生涯最后都推动了什么函数的合入。

Go1.23 方法/函数优化

slices.Repeat

这是一个今年(2024 年)才提出的新提案,原提案作者提供给功能介绍时,还给出了其他语言的相关案例。很快受到了 Go 官方团队的响应并通过。

0b0970cd752c2eca7020f1fb32981eba.png

函数签名:

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 年的旧提案转化过来,目的上是为了更安全地将目标文件复制到本地文件系统,认为可以帮助到很多场景。

602566cf6e02fa22b5f73b22a1ab6546.png

函数签名:

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 标准库中新增了如下两个方法:

  1. ParseCookie

  2. 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 新版本的新方法、函数,目前来看这些函数没有特别大的功能调整,主要都是对于日常工程开发上的优化。

这些新调整也算是针对开发效率的一定的提效了,大家可以及时用到工作的开发上!

推荐阅读

参考资料

[1]

x/net/http/httpguts: add ParseCookie and ParseSetCookie: https://github.com/golang/go/issues/25194

关注和加煎鱼微信,

一手消息和知识,拉你进技术交流群👇

99397fd88d81eea65d8d5bd4be08f394.jpeg

3edb0c17d4c81696230fbcd5637bb2d6.png

你好,我是煎鱼,出版过 Go 畅销书《Go 语言编程之旅》,再到获得 GOP(Go 领域最有观点专家)荣誉,点击蓝字查看我的出书之路

日常分享高质量文章,输出 Go 面试、工作经验、架构设计,加微信拉读者交流群,和大家交流!

原创不易 点赞支持

  • 24
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值