Go:Stringer 命令,通过代码生成提高效率

Go

ℹ️ 这个文章基于 Go 1.13.

stringer命令旨在自动创建满足[fmt.Stringer](https://golang.org/pkg/fmt/#Stringer) String(),并将它们描述为字符串。

#案例

命令文档 提供了一个示例,供我研究该命令使用。就是这种情况:

Go

这里是输出:

1

用常量值生成日志可能会有些混乱。

让我们用命令stringer -type=Pill:生成 String() 方法:

Go

一个新的函数String()已经生成。这是运行先前代码时的新输出:

Aspirin

现在,该类型将自身描述为字符串,而不是其内部值。

stringer还可与go generate命令完美配合,使其功能更强大。只需在代码中添加以下指令即可:

Go

然后,运行“ go generate”命令将自动为所有类型生成新函数。

#效率

stringer生成一个字符串,其中包含值列表作为字符串,以及一个数组,其中包含每个字符串的索引。在我们的示例中,读取Aspirin将包括从索引7到13读取字符串

Go

但是它有多快和高效?让我们与其他两个解决方案进行比较:

-使用硬编码值生成String()函数:

Go

这是一个包含二十个值的列表的基准:

name time/op
Stringer-4 4.16ns ± 2%
StringerWithSwitch-4 3.81ns ± 1%

这是具有一百个值的相同基准:

name time/op
Stringer-4 4.96ns ± 0%
StringerWithSwitch-4 4.99ns ± 1%

您拥有的常数越多,效率越高。这实际上是有道理的。与通过一些跳转指令(表示“ if”条件的汇编指令)相比,从内存中加载值的开销更大。
但是,开关越大,跳转指令的数量就越大。从某个角度来看,从内存中加载将变得更加有效。

  • String() 函数生成了一个 map:

Go

下面是一个包含20个常量的基准:

name time/op
Stringer-4 4.16ns ± 2%
StringerWithMap-4 28.60ns ± 2%

使用map要慢得多,因为它必须进行函数调用,而且bucket中的查找并不像访问切片的索引那么简单。
有关地图及其内部结构的更多信息,我建议您阅读我的文章 “Go: Map Design by Code.”

#自检程序

在生成的指令中,有些纯粹是出于验证目的而创建的。以下是这些说明:

Go

stringer将常量的名称与该值一起写在每一行上。在此示例中,“阿司匹林”的值为“ 2”。更新常量名称或其值将产生错误:

  • 更新名称而不重新生成String()函数:

./pill_string.go: 12: 8: undefined: Aspirin

  • 更新值而不重新生成String()函数:

./pill_string.go:12 :7 : invalid array index Aspirin - 1 (out of bounds for 1-element array)./pill_string.go: 13 :7 : invalid array index Ibuprofen - 2 (index must be non-negative

但是,如果我们添加新常量 (此处,下一个键是数字”3”),并且不更新生成的文件,”stringer”具有默认值:

Pill(3)

添加此自检不会产生任何影响,因为它在编译时已被删除。可以通过查看生成的[asm]来确认(https://golang.org/doc/asm)程序代码:

go tool compile -S main.go pill_string.go | grep “"".Pill.[^\s]* STEXT”“”.Pill.String STEXT size=275 args=0x18 locals=0x50

二进制文件中只有String()函数导出。检查对性能或二进制大小没有开销。

常数越多,效率就越高。这实际上是有道理的。从内存加载值比通过某些跳转指令(表示”if”条件的程序集指令)更广泛。
但是,交换机越大,跳转指令的数量就越多。从某个点开始,从内存加载将变得更加有效。

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://medium.com/a-journey-with-go/go-...

译文地址:https://learnku.com/go/t/45620

本文为协同翻译文章,如您发现瑕疵请点击「改进」按钮提交优化建议
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!