本文介绍一下Go1.22比较重要的几个新特性。
for
Go1.22版本中最大的变化是对于for循环的,有两处较大的更新:
- 之前的for循环每次循环中的变量只创建一次,每次循环。go1.22版本开始,每次循环都会创建新的变量。
- for range 直接支持变量整数。
下面用示例演示,首先安装go1.22
1
2
go install golang.org/dl/go1.22.1@latest
go1.22.1 download
loopvar示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main
import (
"fmt"
"sync"
)
func main() {
wg := sync.WaitGroup{}
wg.Add(3)
arr := []int{1, 2, 3}
for _, x := range arr {
go func() {
fmt.Println(x)
wg.Done()
}()
}
wg.Wait()
}
1
2
3
4
5
6
7
8
9
10
>go version
go version go1.20.2 darwin/arm64
>go run main.go
3
3
3
>go1.22.1 run main.go
3
1
2
上面示例可以看出,当使用go 1.20.2 版本执行时输出的都是3。这是因为变量x在各个迭代中只声明了一个变量,所以在每次迭代中的goroutine中输出的都是循环结束后的最后的值。这在golang中一直被称为for range的坑。
而当使用go 1.22.1版本执行则是分别输出的,这也就是说每次迭代的变量x都是一个新的变量。
这可能是一个潜在破坏式的更新。关于它的变更会在go.mod文件中版本为go1.22.0及之后的版本才会生效,当然如果直接使用go run执行也会直接应用新特性的。
range示例
1
2
3
4
5
6
7
8
9
10
11
package main
import (
"fmt"
)
func main() {
for x := range 3 {
fmt.Println(x)
}
}
1
2
3
4
>go1.22.1 run main.go
0
1
2
rand
Go1.22中新增了math/rand/v2包,这是Go第一次在标准库中添加v2的包。后续版本的更新中其它包也可能会引入v2版本。
增强路由匹配
Go1.22中的http.ServeMux功能增强:
- “POST /items/create” 将直接匹配到路径”/items/create”的POST请求。
- 路径支持参数匹配,例如/items/{id}的路径可以使用 Request.PathValue(“id”) 获取到URL路径中id的值。
- “…“通配符。例如”/files/{path…}”, 它必须放在末尾,表示匹配所有剩余的段。
- 若要匹配确切的路径,可以在路径末尾增加”{$}”,例如: “/exact/match/{$}”。
http路由匹配的变更,可以使用 GODEBUG 变量来控制,通过设置 httpmuxgo121=1 恢复为之前旧版本的路径匹配行为。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package main
import (
"fmt"
"net/http"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("POST /items/create", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "created")
})
mux.HandleFunc("/items/{id}", func(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id")
fmt.Fprint(w, "you got id: "+id)
})
mux.HandleFunc("/files/{path...}", func(w http.ResponseWriter, r *http.Request) {
path := r.PathValue("path")
fmt.Fprint(w, "you got path: "+path)
})
mux.HandleFunc("/exact/match/{$}", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "match")
})
http.ListenAndServe(":8086", mux)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
>GODEBUG="httpmuxgo121=0" go1.22.1 run main.go
>curl -X POST http://localhost:8086/items/create
created
>curl http://localhost:8086/items/123
you got id: 123
>curl http://localhost:8086/files/abc
you got path: abc
>curl http://localhost:8086/files/abc/def
you got path: abc/def
>curl http://localhost:8086/exact/match/
match
>curl http://localhost:8086/exact/match
<a href="/exact/match/">Moved Permanently</a>.
>curl http://localhost:8086/exact/match/1
404 page not found