golang拾遗:为什么我们需要泛型( 五 )


解决这个问题不难 , 一条路是golang官方提供内置类型的包装类型 , 并且实现java那样的自动拆装箱 。 另一条路是支持类似rust的运算符重载 , 例如add代表+ , mul代表* , 这样只需要将内置运算符进行简单的映射即可兼容内置类型 , 同时又能满足自定义类型 。 不过鉴于golang官方一直对运算符重载持否定态度 , 方案2也只能想想了 。
另一个黑暗面就是泛型如何实现 , 现有的主流方案不是类型擦除(java , typescript) , 就是将泛型代码看作模板进行实例化代码生成(c++ , rust) , 另外还有个另类的c#在运行时进行实例化 。
目前社区仍然偏向于模板替换 , 采用类型字典的方案暂时无法处理泛型struct , 实现也非常复杂 , 所以反对声不少 。 如果最终敲定了模板方案 , 那么golang要面对的新问题就是链接时间过长和代码膨胀了 。 一份泛型代码可以生产数份相同的实例 , 这些实例需要在链接阶段被链接器剔除 , 这会导致链接时间爆增 。 代码膨胀是老生常谈的问题了 , 更大的二进制文件会导致启动更慢 , 代码里的杂音更多导致cpu缓存利用率的下降 。
链接时间的优化社区有人提议可以在编译期标记各个实例提前去重 , 因为golang各个代码直接是有清晰的联系的 , 不像c++文件之间单独编译最终需要在链接阶段统一处理 。 代码膨胀目前没有办法 , 而且代码膨胀会不会对性能产生影响 , 影响多大能否限定在可接受范围都还是未知数 。
但不管怎么说 , 我们都需要泛型 , 因为带来的远比失去的要多 。
最后 , 小编想说:我是一名python开发工程师 , 整理了一套最新的python系统学习教程 , 想要这些资料的可以关注私信小编“01”即可 , 希望能对你有所帮助 。