Golang 高效编写(整理)

这是一篇如何编写高效 Golang 语言程序的文章。这是从一些开发者的经验总结中整理出来的。根据这篇文章,你可以编写出一篇更高效的 Golang 程序。

尽量使用直接的类型

interface{} 提供了 golang 中的 interface 类似于 java 的 interface、PHP 的 interface 或 C++ 的纯虚基类。通过这种方式可以提供更快捷的编码。但是这种方式也带来了一些问题,最大的问题还是性能问题。

1
2
3
4
5
6
7
8
// method 1
a.AA()
// method 2
v.(InterfaceA).AA()
// method 3
switch v.(type) {
case InterfaceA:
v.(InterfaceA).AA()}

这三组方法性能逐个下降,最好的方式是直接进行类型引用。

指针传参效率更高

指针传参会减少对象复制过程,效率更高。

1
func Call(a *Struct) uint64 {return a.Ba}

创建对象时避免创建引用

上面的方法效率要比下面的方法效率更高:

1
2
3
4
5
// method 1
new(Struct)
Struct{}
// method 2
&BigStruct{}

range 遍历

常见的 range 方式通常是如下的方式:

1
2
for k,v := range slices {log.Println(v)
}

或者是省略 k,使用 v 就可以遍历整个 slices。但是,实际上下面这个方法会更快,原因是这里面节省了 v 的拷贝,速度要比拷贝更快:

1
2
for k,_ := range slices {log.Println(slices[k])
}

更快的运算

除法运算更慢,尝试变成乘法吧。嗯,就是这样。

更快的结构体

map 方式的结构体,其他的数据方式,性能方式相差不大。效率上,硬编码 > 指针 slice 的 range 循环 > for 循环,需要根据具体环境选择,毕竟相差不大。

反射会影响性能

除非必要情况下,减少反射可以提升程序的整体性能。

避免大量重复创建对象

会对 GC 造成负担,目前 Golang 的 GC 会导致程序暂停。连续小内存分配会导致大量的 cpu 消耗在 scanblock 这个函数上;连续 make([]T, size) 来分配 slice 还会额外导致 cpu 消耗在 runtime.memclr 函数上。