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

Posted 文大侠666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

func TestMultiWrap(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 := []int1, 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代码来实现如下

func OldBytesToString(b []byte) string 
	return *((*string)(unsafe.Pointer(&b)))


func OldStringToBytes(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 将会被标注为被废弃。
互转代码大大简化,可如下实现

func NewBytesToString(b []byte) string 
	return unsafe.String(&b[0], len(b))


func NewStringToBytes(s string) []byte 
	return unsafe.Slice(unsafe.StringData(s), len(s))

时间格式化和比较

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

func TestTimeFormat(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方法,比较上更加直观和方便

func TestTimeCompare(t *testing.T) 
	tm1 := time.Now()
	tm2 := time.Now()

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

参考

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

以上是关于golang 1.20正式发布,更好更易更强的主要内容,如果未能解决你的问题,请参考以下文章

房价要大涨?!加拿大刚刚宣布放松压力测试,买房更易更轻松

封装一个加密包,让敏感数据更易脱敏 Golang | Go语言

封装一个加密包,让敏感数据更易脱敏 Golang | Go语言

封装一个加密包,让敏感数据更易脱敏 Golang | Go语言

定义类(和嵌套类)成员函数的更好/更整洁/更易读的方法? [复制]

更快,可扩展性更强的 Apache Cassandra 4.0 正式发布