繁体   English   中英

去隐式转换到接口做内存分配?

[英]Go implicit conversion to interface does memory allocation?

当使用类型为interface{}可变参数(例如Printf )定义函数时,参数显然会隐式转换为接口实例。

此转换是否意味着内存分配? 转换速度快吗? 当关注代码效率时,我应该避免使用可变参数函数吗?

我发现关于Go中接口内存分配的最佳解释仍然来自Rus Cox,这是Go的核心程序员之一。 值得一读的是它。

http://research.swtch.com/interfaces

我找到了一些最有趣的部分:

存储在接口中的值可能是任意大的,但只有一个字专用于将值保存在接口结构中,因此赋值在堆上分配一块内存并将指针记录在单字槽中。

...

调用fmt.Printf(),Go编译器生成代码,该代码从itable调用适当的函数指针,将接口值的数据字作为函数的第一个(在此示例中,仅)参数传递。

Go的动态类型转换意味着编译器或链接器预先计算所有可能的itables是不合理的:有太多(接口类型,具体类型)对,并且大多数都不需要。 相反,编译器为每个具体类型生成类型描述结构,如Binary或int或func(map [int] string)。 在其他元数据中,类型描述结构包含由该类型实现的方法的列表。

...

接口运行时通过查找具体类型的方法表中接口类型的方法表中列出的每个方法来计算itable。 运行时在生成它之后缓存itable,因此这种对应只需要计算一次。

...

如果涉及的接口类型为空 - 它没有方法 - 那么除了将指针保持在原始类型之外,itable没有用处。 在这种情况下,可以删除itable,并且值可以直接指向类型。

因为Go具有静态类型的提示以与动态方法查找一起使用,所以它可以将查找从调用站点移回到值存储在接口中的点。

转换为interface{}是与变量参数分开的概念,它包含在切片中,可以是任何类型。 但是,只要它们不会逃逸到堆中(在GC工具链中),这些都可能在分配意义上是免费的。

您将从fmt函数(如Printf中看到的多余分配将来自反射,而不是来自使用interface{}或可变参数。

如果您关注效率,那么避免间接将始终更有效,因此使用正确的值类型将产生更高效的代码。 但差异可能很小,因此在对自己进行微小优化之前先对代码进行基准测试。

Go传递参数copy_by_value,因此它无论如何都会进行内存分配。 如果可能的话,你总是应该更好地避免使用接口{}。 在描述的情况下,您的函数将需要反映使用它们的参数。 反射是相当昂贵的操作,这就是为什么fmt.Printf()如此缓慢。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM