2016-09-14 14:07
浏览 34


When defining a function with variadic arguments of type interface{} (e.g. Printf), the arguments are apparently implicitly converted to interface instances.

Does this conversion imply memory allocation? Is this conversion fast? When concerned by code efficiency, should I avoid using variadic functions?

图片转代码服务由CSDN问答提供 功能建议

使用类型为 interface {} (例如 Printf ),则显然会将参数隐式转换为接口实例。

此转换是否暗示内存分配? 这个转换快吗? 如果担心代码效率,应该避免使用可变参数函数吗?

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

3条回答 默认 最新

  • dsj1961061
    dsj1961061 2016-09-14 14:34

    The best explanation i found about the interface memory allocation in Go is still this article from Rus Cox, one of the core Go programmer. It's well worth to read it.

    I picked up some of the most interesting parts:

    Values stored in interfaces might be arbitrarily large, but only one word is dedicated to holding the value in the interface structure, so the assignment allocates a chunk of memory on the heap and records the pointer in the one-word slot.


    Calling fmt.Printf(), the Go compiler generates code that calls the appropriate function pointer from the itable, passing the interface value's data word as the function's first (in this example, only) argument.

    Go's dynamic type conversions mean that it isn't reasonable for the compiler or linker to precompute all possible itables: there are too many (interface type, concrete type) pairs, and most won't be needed. Instead, the compiler generates a type description structure for each concrete type like Binary or int or func(map[int]string). Among other metadata, the type description structure contains a list of the methods implemented by that type.


    The interface runtime computes the itable by looking for each method listed in the interface type's method table in the concrete type's method table. The runtime caches the itable after generating it, so that this correspondence need only be computed once.


    If the interface type involved is empty—it has no methods—then the itable serves no purpose except to hold the pointer to the original type. In this case, the itable can be dropped and the value can point at the type directly.

    Because Go has the hint of static typing to go along with the dynamic method lookups, it can move the lookups back from the call sites to the point when the value is stored in the interface.

    点赞 评论
  • duan02468
    duan02468 2016-09-14 14:23

    Go passes arguments copy_by_value, so it does memory allocation anyway. You always should better avoid using interface{} if possible. In described case your function will need to reflect arguments to use them. Reflection is quite expensive operation that's why fmt.Printf() is so slow.

    点赞 评论
  • dongtaigan1594
    dongtaigan1594 2016-09-14 14:28

    Converting to an interface{} is a separate concept from variadic arguments which are contained in a slice and can be of any type. However these are all probably free in the sense of allocations as long as they don't escape to the heap (in the GC toolchain).

    The excess allocations you would see from fmt functions like Printf are going to be from reflection rather than from the use of interface{} or variadic arguments.

    If you're concerned with efficiency though, avoiding indirection will always be more efficient than not, so using the correct value types will yield more efficient code. The difference can be minimal though, so benchmark the code first before concerning yourself with minor optimizations.

    点赞 评论