Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
4 contributors

Users who have contributed to this file

@Sergobot @radarhere @notjrbauer @luciotato
67 lines (47 sloc) 2.56 KB

This is what I understand happens at low-level when you use interface parameters/vars

Golang Interfaces

A golang-Interface is a class with no fields and ONLY VIRTUAL methods.

    type J interface 
       to-string() ( string )
       dosomea ( x, J )
       dosomeb ( x, k ) (J) 
       dosomec ( x, a string) ( int )

If a struct implements such methods, it “satisfies the interface”.

You can create a “var of type interface” or declare a function param of type interface.

  • a var x of type interface is NIL until a concrete-type its assigned to it.
  • a var x of type interface is internally just 2 pointers. One pointer to an ITable and other to the concrete value stored.

so var x J-interface internally is:

    c-struct interface-var
		ITable            *ITable
		concrete-value    any_union

an ITable is:

    c-struct ITable
           concrete-type  *type
       	   interface-type *interface
           jmp-table[]    *function

When a concrete type is assigned to a interface-var, golang *creates a jmp-method table on the fly (and caches it). There is a jmp-table for each combination of J-Interface * concrete-type-implementing-J-interface

Let’s assume z is struct Z and there is a bunch of functions as func dosomex ( z ){...} so that struct Z implements interface J

When you do:

     var x J-interface  = z

golang constructs the ITable on the fly. The J-interface has 4 methods, so it needs to calculate x.ITable. Golang will search the method “to-string” of struct Z and put it in ITable.jmp-table[0], then look for “dosomea (struct Z)” and put it in ITable.jmp-table[1] and so on. Then it will store ITable->concrete = &struct-Z, and X.itable->interface= &interface-J”.

x, being an interface type, has two 32bit pointers, the first will point to the newly created ITable “&struct-Z, &interface-J, jmp-table[0...3]” (where the concrete-type-info is stored) and the second points to the concrete-value (in this case a copy of z)

then…

    for n:=1; n++<100 {
         print( x.dosomea(x))
    }

the call x.dosomea() is:

  • x is var type interface -> struct Z, Interface J
  • so x.ITable -> “struct-Z,interface-J,jmp-table[0..3]”
  • x.dosomea() gets translated to call [x.ITable.jmps[1]] (since “dosomea” => index 1)
  • this is a memory fetch and an indirect-call.
  • interface values are passed by value, so x.ITable and x.value are always available in the stack. To know the concrete type stored in x.value golang must dereference c.ITable->concrete-type.
You can’t perform that action at this time.