0


golang 1.20正式发布,更好更易更强

预期中的Go 2不会有了,1.20也算是一个小gap,从中可以一窥Go未来的发展之路。对于Go来说,未来保持1.x持续演进和兼容性之外,重点就是让Go性能更优,同时保持大道至简原则,使用尽可能容易,从这两个方面带大家看看你1.20值得关注的特性。

优化相关

编译速度

1.18引入泛型,降低了编译速度,这一般版本基本上优化和1.17平齐,当前1.20的编译也是依赖Go 1.17版本自举。如果没泛型刚需的,可以等到1.20稳定后升级。

内存优化area

引入新的内存分配机制arena,支持手动管理内存,部分场景提升5%-15%,可参考golang新特性arena,带你起飞。

编译优化pgo

全称Profile-guided optimization (PGO),也是一项新的优化技术,通常提升3%-4%,简单说就是先跑一遍程序生成pprof文件,然后基于此文件引导编译器优化再编译一遍。当前只实现内联的优化,后续可能增加多种优化,个人理解有点类似离线版本JIT。

发行体积

安装包安装,$GOROOT/pkg 目录将不再存储标准库的预编译包存档,相比之前减少1/3。

默认禁用 CGO

在没有C toolchain的系统上默认禁用 CGO,相比依赖CGO的标准库,此情况编译只依赖pure Go。

代码编写

可以看到,Go新版本代码编写演进总的原则就是简化写代码的心智负担,普通开发者只需要关心实现即可,尽可能少的和底层实现绑定。

多error wrap

在1.13基础上,增加多error wrap的能力,类似功能不用再依赖外部库(hashicorp/go-multierror库等)。
使用很简单,如下,多个%w格式化即可wrap,同时支持Is和As

funcTestMultiWrap(t *testing.T){
    err1 := errors.New("Error 1")
    err2 := errors.New("Error 2")
    err3 := errors.New("Error 3")

    err := fmt.Errorf("%w,%w,%w", err1, err2, err3)

    fmt.Printf("wrap errors:%v\n", err)

    fmt.Printf("is err1:%v, is err2:%v, is err3:%v\n",
        errors.Is(err, err1),
        errors.Is(err, err2),
        errors.Is(err, err3))}

输出

wrap errors:Error 1,Error 2,Error 3
is err1:true, is err2:true, is err3:true

slice转array

在1.20之前,slice转array需要了解底层原理,如下实现,不是特别直观

    slice :=[]int{1,2,3,4,5}// 老方法
    array1 :=*(*[5]int)(slice)

1.20引入直接转换实现,降低新手入门难度,更加直观,如下操作即可

//新方法// 1.20之前报错 cannot convert slice (variable of type []int) to type [5]int
    array2 :=[5]int(slice)//array22 := [6]int(slice)//fmt.Printf("Array:%v\n", array22)

注意目标数组长度不能大于slice长度,否则报错

// panic: runtime error: cannot convert slice with length 5 to array or pointer to array with length 6

bytes string互转

在1.20之前,bytes/string互转需要了解底层实现,借助unsafe代码来实现如下

funcOldBytesToString(b []byte)string{return*((*string)(unsafe.Pointer(&b)))}funcOldStringToBytes(s string)[]byte{
    stringHeader :=(*reflect.StringHeader)(unsafe.Pointer(&s))var b []byte
    pbytes :=(*reflect.SliceHeader)(unsafe.Pointer(&b))// 先引用,防止原有string gc
    pbytes.Data = stringHeader.Data
    pbytes.Len = stringHeader.Len
    pbytes.Cap = stringHeader.Len

    return b
}

1.20中,官方提供如下三个函数包装下底层实现

  • func String(ptr *byte, len IntegerType) string:根据数据指针和字符长度构造一个新的 string。
  • func StringData(str string) *byte:返回指向该 string 的字节数组的数据指针。
  • func SliceData(slice []ArbitraryType) *ArbitraryType:返回该 slice 的数据指针。

以往常用的 reflect.SliceHeader 和 reflect.StringHeader 将会被标注为被废弃。
互转代码大大简化,可如下实现

funcNewBytesToString(b []byte)string{return unsafe.String(&b[0],len(b))}funcNewStringToBytes(s string)[]byte{return unsafe.Slice(unsafe.StringData(s),len(s))}

时间格式化和比较

在1.20之前,时间格式化只能用别扭的2006-01-02 15:04:05语法,可能创始人觉得Geek吧,扛不住刚需,现在终于支持常见的如下三种格式化语法,不知道啥时候能把YYmmdd加进来

funcTestTimeFormat(t *testing.T){
    tm1 := time.Now()

    fmt.Printf("DateTime-%v\nDateOnly-%v\nTimeOnly-%v\n",
        tm1.Format(time.DateTime),
        tm1.Format(time.DateOnly),
        tm1.Format(time.TimeOnly))}

输出

DateTime-2023-02-09 00:43:13
DateOnly-2023-02-09
TimeOnly-00:43:13

另外就是,相比之前的After/Before比较,新引入一个Compare方法,比较上更加直观和方便

funcTestTimeCompare(t *testing.T){
    tm1 := time.Now()
    tm2 := time.Now()

    c := tm1.Compare(tm2)if c ==-1{
        fmt.Println("tm1 < tm2")}elseif c ==0{
        fmt.Println("tm1 = tm2")}elseif c ==1{
        fmt.Println("tm1 > tm2")}}

参考

代码 https://gitee.com/wenzhou1219/go-in-prod/tree/master/go_120_feature

  • Go1.20 那些事:错误处理优化、编译速度提高、PGO 提效等新特性,你知道多少?
  • Go 1.20 is released! - The Go Programming Language
  • What’s New in Go 1.20, Part I: Language Changes
  • Exploring Go’s Profile-Guided Optimizations
  • PGO 是啥,咋就让 Go 更快更猛了?
  • GopherCon 2022: Russ Cox - Compatibility: How Go Programs Keep Working: https://www.youtube.com/watch?v=v24wrd3RwGo

本文转载自: https://blog.csdn.net/wenzhou1219/article/details/128945983
版权归原作者 文大侠666 所有, 如有侵权,请联系我们删除。

“golang 1.20正式发布,更好更易更强”的评论:

还没有评论