在go里面将struct从interface{}转换成为具体类型,即做type switching操作的时候,会有memory allocation,确实会有一定的性能消耗,更多可以参考:Go: The price of interface{}
因为go目前仍然没有泛型支持(据说go 2.0版本会有),所以常见的作法是使用代码生成,即,针对使用到的类型,都生成出来相应的函数,这也是 @北南 的回答中介绍的做法。
我这里再做一点点补充。
比方说,我们以下函数:
当我们不知道参数类型的时候,只能无脑调用HTMLEscVar,那么即便传进来的参数类型是string / int,也会因为对interaface{}做type switch操作而产生内存占用损耗性能。
如果是人肉编写的代码,程序员可以很容易根据调用函数传参的具体类型去改用 HTMLEscInt 或者 HTMLEscStr 版本,以避免类型转换提高性能。
但如果是模板生成出来的代码就未必,在做代码生成的时候,往往是简单的字符串拼接、替换,并没有对所生成代码做强类型的校验,也就是说,只能生成调用HTMLEscVar版本的代码。
幸运的是 go/types 包提供了对go代码做静态分析、获取类型的能力;代码生成出来后,把源码都丢给go/types分析,然后根据参数的具体类型,去替换成为具体的版本。
最近我在给gorazor做性能优化,使用了上述技巧后,终于把模板渲染做到了zero memory allocation,性能可以达到quicktemplate的两倍。