Go语言高质量编程(2)

72 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 6 天,在第五天的基础上学习了性能优化的建议

在Go语言中自带了一个包,叫test,该包包含了单元测试和性能基准测试,而性能基准测试benchmark是我们在性能优化时需要使用的工具之一

基准测试

基准测试就是在一定的工作负载之下检测程序性能的一种方法。基准测试的基本格式如下:

 func BenchmarkName(b *testing.B){
     // ...
 }

基准测试以Benchmark为前缀,需要一个*testing.B类型的参数b,基准测试必须要执行b.N次,这样的测试才有对照性,b.N的值是系统根据实际情况去调整的,从而保证测试的稳定性。

为Split函数编写基准测试函数

 func BenchmarkSplit(b *testing.B) {
     for i := 0; i < b.N; i++ {
         Split("a:b:c", ":")
     }
 }

基准测试并不会默认执行,需要增加-bench参数,所以我们通过执行go test -bench=Split命令执行基准测试

image-20230127232131162.png

注意: 若想运行所有基准测试函数,需要在-bench后面加上点,有两种写法,写法一:-bench=".",写法二:-bench .。不能直接-bench=.,在Windows下直接这样子写的话结果是不会运行任何基准测试的用例

6041946和194.6ns/op表示每次调用Split函数耗时194.6ns,这个结果是6041946次调用的平均值

在编写代码过程中,很多时候会使用到动态分配内存,因此需要了解部分go语言的底层原理,才能方便我们进行性能优化

slice

slice在go语言中称为切片,是一种数据结构,被用作go语言里面数组的描述符,并且切片是可以动态增长的

在go语言中,slice的底层结构如下

 type slice struct {
     array unsafe.Pointer
     len int
     cap int
 }

array表示切片指向的底层数组,每个切片都会指向一个底层数组,对切片的操作本质上是对于底层数组的操作

len是当前切片中所含有元素的个数

cap是在不进行内存分配(切片扩容)的情况下,切片可以容纳最大的元素个数,cap≥len

go语言中可以使用make() 来创建一个切片,在创建时必须要指定切片的类型以及长度len。若知道cap可以提前使用cap来定义切片,为切片预分配空间,这样能达到性能优化的目的,减少程序在执行过程中重复对切片进行扩容的操作

同理,map作为一种在go中的数据结构,也是使用make()函数来进行创建,依然可以在已知map大小的情况下,在创建的时候指定map可以存放的数据大小。map和slice都能进行动态扩容