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

ℹ️ 本文基于Go 1.13。

stringer命令旨在自动创建满足fmt.Stringer的方法。 它为指定类型生成String()并将其描述为字符串。常可用于​定义错误码时同时生成错误信息等场景。​

案例

该命令的文档提供了一个该命令的示例。 如下:

这里是输出:

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

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

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

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

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

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

效率

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

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

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

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

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

您拥有的常数越多,效率越高。 这实际上是有道理的。 从内存中加载值比执行一些跳转指令(表示if条件的汇编指令)要耗费更多的时间。但是,switch越大,跳转指令的数量就越大。 从某个角度来看,从内存中加载将变得更加有效。

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

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

使用map的速度要慢得多,因为它必须进行函数调用,并且存储桶中的查找不像访问切片索引那样简单。

自检

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

stringer将每行的常量名称与该值一起写入。 在此示例中,Aspirin的值为2。更新常量名称或其值将生成错误:

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

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

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

添加此自检不会产生任何影响,因为在编译时将其删除。 可以通过查看程序生成的asm代码来确认:

只有String()函数以二进制形式导出。 该检查没有性能或二进制大小的开销。

编译整理自  Go: Stringer Command, Efficiency Through Code Generation


欢迎订阅我的公众号,文章更新早知道
张贴在Go标签:

版权声明: 本文为【陈思敏捷】的原创文章。
原文链接:【https://www.chenjie.info/2496】。原文标题:【Go:Stringer命令,通过代码生成提高效率】。文章转载请联系作者。


发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据