{"id":47322,"date":"2015-03-05T17:33:02","date_gmt":"2015-03-05T14:33:02","guid":{"rendered":"https:\/\/www.altoros.com\/blog\/?p=47322"},"modified":"2019-11-27T18:06:39","modified_gmt":"2019-11-27T15:06:39","slug":"golang-internals-part-2-diving-into-the-go-compiler","status":"publish","type":"post","link":"https:\/\/www.altoros.com\/blog\/golang-internals-part-2-diving-into-the-go-compiler\/","title":{"rendered":"Golang Internals, Part 2: Diving Into the Go Compiler"},"content":{"rendered":"<p><center><small>All parts: <a href=\"https:\/\/www.altoros.com\/blog\/golang-internals-part-1-main-concepts-and-project-structure\/\">Part 1<\/a> | <strong>Part 2<\/strong> | <a href=\"https:\/\/www.altoros.com\/blog\/golang-internals-part-3-the-linker-object-files-and-relocations\/\">Part 3<\/a> | <a href=\"https:\/\/www.altoros.com\/blog\/golang-internals-part-4-object-files-and-function-metadata\/\">Part 4<\/a> | <a href=\"https:\/\/www.altoros.com\/blog\/golang-internals-part-5-the-runtime-bootstrap-process\/\">Part 5<\/a> | <a href=\"https:\/\/www.altoros.com\/blog\/golang-internals-part-6-bootstrapping-and-memory-allocator-initialization\/\">Part 6<\/a><\/small><\/center><\/p>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignright  wp-image-47323\" style=\"margin:20px\" alt=\"golang-internals-the-go-compiler\" src=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2019\/10\/golang-internals-the-go-compiler.png\" width=\"132\" height=\"162\" \/><\/p>\n<p>Do you know what exactly happens in the Go runtime, when you use a variable via interface reference? This is not a trivial question, because in Go a type that implements an interface does not contain any references to this interface whatsoever. Still, we can try answering it, using our knowledge of the Go compiler, which was discussed in the <a href=\"https:\/\/www.altoros.com\/blog\/golang-internals-part-1-main-concepts-and-project-structure\/\" target=\"_blank\" rel=\"noopener noreferrer\">previous<\/a> blog post.<\/p>\n<p>So, let\u2019s take a deep dive into the Go compiler: create a basic Go program and see the internal workings of the Go typecasting. Using it as an example, we\u2019ll explain how a node tree is generated and utilized. So, you can further apply this knowledge to other Go compiler\u2019s features.<\/p>\n<p>&nbsp;<\/p>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_79_2 counter-hierarchy ez-toc-counter ez-toc-transparent ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/www.altoros.com\/blog\/golang-internals-part-2-diving-into-the-go-compiler\/#Before_you_start\" >Before you start<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/www.altoros.com\/blog\/golang-internals-part-2-diving-into-the-go-compiler\/#Creating_a_simple_Go_program\" >Creating a simple Go program<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/www.altoros.com\/blog\/golang-internals-part-2-diving-into-the-go-compiler\/#Understanding_the_node_tree_of_the_main_method\" >Understanding the node tree of the main method<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/www.altoros.com\/blog\/golang-internals-part-2-diving-into-the-go-compiler\/#How_the_compiler_translates_the_assignment_node\" >How the compiler translates the assignment node<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/www.altoros.com\/blog\/golang-internals-part-2-diving-into-the-go-compiler\/#Inside_the_getitab_method\" >Inside the getitab method<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/www.altoros.com\/blog\/golang-internals-part-2-diving-into-the-go-compiler\/#Further_reading\" >Further reading<\/a><\/li><\/ul><\/nav><\/div>\n<h3><span class=\"ez-toc-section\" id=\"Before_you_start\"><\/span>Before you start<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>To perform the experiment, we will need to work directly with the Go compiler (not the Go tool). You can access it by using the command below.<\/p>\n<pre style=\"padding-left:20px;\">go tool 6g test.go<\/pre>\n<p>It will compile the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">test.go<\/code> source file and create an object file. Here, <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">6g<\/code> is the name of the compiler on our machine that has the AMD64 architecture. Note that you should use different compilers for different architectures.<\/p>\n<p>When we work directly with the compiler, we can use some handy command line arguments (more details in the <a href=\"https:\/\/pkg.go.dev\/cmd\/gc#hdr-Command_Line\" target=\"_blank\" rel=\"noopener noreferrer\">official docs<\/a>). For the purposes of this experiment, we\u2019ll need the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">-W<\/code> flag that will print the layout of the node tree.<\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Creating_a_simple_Go_program\"><\/span>Creating a simple Go program<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>First of all, we are going to create a sample Go program. You will find our version below.<\/p>\n<p><code language=\"go;\"><br \/>\n  1  package main<br \/>\n  2<br \/>\n  3  type I interface {<br \/>\n  4          DoSomeWork()<br \/>\n  5  }<br \/>\n  6<br \/>\n  7  type T struct {<br \/>\n  8          a int<br \/>\n  9  }<br \/>\n 10<br \/>\n 11  func (t *T) DoSomeWork() {<br \/>\n 12  }<br \/>\n 13<br \/>\n 14  func main() {<br \/>\n 15          t := &amp;T{}<br \/>\n 16          i := I(t)<br \/>\n 17          print(i)<br \/>\n 18  }<\/code><\/p>\n<p>Really simple, isn\u2019t it? The only thing that might seem unnecessary is the 17th line, where we provide the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">i<\/code> variable. Nevertheless, without it, <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">i<\/code> will remain unused and the program will not be compiled. The next step is to compile our program using the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">-W<\/code> switch.<\/p>\n<pre style=\"padding-left:20px;\">go tool 6g -W test.go<\/pre>\n<p>After doing this, you will see output that contains node trees for each method defined in the program. In our case, these are the main and <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">init<\/code> methods. The latter is here, because it is implicitly defined for all programs, but we actually do not care about it right now.<\/p>\n<p>For each method, the compiler prints two versions of the node tree. The first one is the original node tree that we get after parsing the source file. The second one is the version that we get after type checking and applying all the necessary modifications.<\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Understanding_the_node_tree_of_the_main_method\"><\/span>Understanding the node tree of the main method<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Let\u2019s take a closer look at the original version of the node tree from the main method and try to understand what exactly is going on.<\/p>\n<pre style=\"padding-left: 20px;\">DCL l(15)\r\n.   NAME-main.t u(1) a(1) g(1) l(15) x(0+0) class(PAUTO) f(1) ld(1) tc(1) used(1) PTR64-*main.T\r\n\r\nAS l(15) colas(1) tc(1)\r\n.   NAME-main.t u(1) a(1) g(1) l(15) x(0+0) class(PAUTO) f(1) ld(1) tc(1) used(1) PTR64-*main.T\r\n.   PTRLIT l(15) esc(no) ld(1) tc(1) PTR64-*main.T\r\n.   .   STRUCTLIT l(15) tc(1) main.T\r\n.   .   .   TYPE &lt;S&gt; l(15) tc(1) implicit(1) type=PTR64-*main.T PTR64-*main.T\r\n\r\nDCL l(16)\r\n.   NAME-main.i u(1) a(1) g(2) l(16) x(0+0) class(PAUTO) f(1) ld(1) tc(1) used(1) main.I\r\n\r\nAS l(16) tc(1)\r\n.   NAME-main.autotmp_0000 u(1) a(1) l(16) x(0+0) class(PAUTO) esc(N) tc(1) used(1) PTR64-*main.T\r\n.   NAME-main.t u(1) a(1) g(1) l(15) x(0+0) class(PAUTO) f(1) ld(1) tc(1) used(1) PTR64-*main.T\r\n\r\nAS l(16) colas(1) tc(1)\r\n.   NAME-main.i u(1) a(1) g(2) l(16) x(0+0) class(PAUTO) f(1) ld(1) tc(1) used(1) main.I\r\n.   CONVIFACE l(16) tc(1) main.I\r\n.   .   NAME-main.autotmp_0000 u(1) a(1) l(16) x(0+0) class(PAUTO) esc(N) tc(1) used(1) PTR64-*main.T\r\n\r\nVARKILL l(16) tc(1)\r\n.   NAME-main.autotmp_0000 u(1) a(1) l(16) x(0+0) class(PAUTO) esc(N) tc(1) used(1) PTR64-*main.T\r\n\r\nPRINT l(17) tc(1)\r\nPRINT-list\r\n.   NAME-main.i u(1) a(1) g(2) l(16) x(0+0) class(PAUTO) f(1) ld(1) tc(1) used(1) main.I<\/pre>\n<p>In the explanation below, we will use an abridged version, from which we removed all the unnecessary details. The first node is rather simple.<\/p>\n<pre style=\"padding-left: 20px;\">DCL l(15)\r\n.   NAME-main.t l(15) PTR64-*main.T<\/pre>\n<p>The first node is a declaration node. <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">l(15)<\/code> tells us that this node is defined in line 15. The declaration node references the name node that represents the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">main.t<\/code> variable. This variable is defined in the main package and is actually a 64-bit pointer to the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">main.T<\/code> type. You can look at line 15 and easily understand what declaration is represented there.<\/p>\n<p>The next one is a bit trickier.<\/p>\n<pre style=\"padding-left: 20px;\">AS l(15) \r\n.   NAME-main.t l(15) PTR64-*main.T\r\n.   PTRLIT l(15) PTR64-*main.T\r\n.   .   STRUCTLIT l(15) main.T\r\n.   .   .   TYPE l(15) type=PTR64-*main.T PTR64-*main.T<\/pre>\n<p>The root node is the assignment node. Its first child is the name node that represents the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">main.t<\/code> variable. The second child is a node that we assign to <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">main.t<\/code>\u2014a pointer literal node (&amp;). It has a child struct literal, which, in its turn, points to the type node that represents the actual type (<code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">main.T<\/code>).<\/p>\n<p>The next node is another declaration. This time, it is a declaration of the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">main.i<\/code> variable that belongs to the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">main.I<\/code> type.<\/p>\n<pre style=\"padding-left: 20px;\">DCL l(16)\r\n.   NAME-main.i l(16) main.I<\/pre>\n<p>Then, the compiler creates another variable, <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">autotmp_0000<\/code>, and assigns the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">main.t<\/code> variable to it.<\/p>\n<pre style=\"padding-left: 20px;\">AS l(16) tc(1)\r\n.   NAME-main.autotmp_0000 l(16) PTR64-*main.T\r\n.   NAME-main.t l(15) PTR64-*main.T<\/pre>\n<p>Finally, we came to the nodes that we are actually interested in.<\/p>\n<pre style=\"padding-left: 20px;\">AS l(16) \r\n.   NAME-main.i l(16)main.I\r\n.   CONVIFACE l(16) main.I\r\n.   .   NAME-main.autotmp_0000 PTR64-*main.T<\/pre>\n<p>Here, we can see that the compiler has assigned a special node called <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">CONVIFACE<\/code> to the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">main.i<\/code> variable. However, this does not give us much information about what&#8217;s happening under the hood. To find out what\u2019s going on, we need to look into the node tree of the main method after all node tree modifications have been applied (you can find this information in the \u201cafter walk main\u201d section of your output).<\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"How_the_compiler_translates_the_assignment_node\"><\/span>How the compiler translates the assignment node<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Below, you can see how the compiler translates our assignment node.<\/p>\n<pre style=\"padding-left: 20px;\">AS-init\r\n.   AS l(16) \r\n.   .   NAME-main.autotmp_0003 l(16) PTR64-*uint8\r\n.   .   NAME-go.itab.*\"\".T.\"\".I l(16) PTR64-*uint8\r\n\r\n.   IF l(16) \r\n.   IF-test\r\n.   .   EQ l(16) bool\r\n.   .   .   NAME-main.autotmp_0003 l(16) PTR64-*uint8\r\n.   .   .   LITERAL-nil I(16) PTR64-*uint8\r\n.   IF-body\r\n.   .   AS l(16)\r\n.   .   .   NAME-main.autotmp_0003 l(16) PTR64-*uint8\r\n.   .   .   CALLFUNC l(16) PTR64-*byte\r\n.   .   .   .   NAME-runtime.typ2Itab l(2) FUNC-funcSTRUCT-(FIELD-\r\n.   .   .   .   .   NAME-runtime.typ\u00b72 l(2) PTR64-*byte, FIELD-\r\n.   .   .   .   .   NAME-runtime.typ2\u00b73 l(2) PTR64-*byte PTR64-*byte, FIELD-\r\n.   .   .   .   .   NAME-runtime.cache\u00b74 l(2) PTR64-*PTR64-*byte PTR64-*PTR64-*byte) PTR64-*byte\r\n.   .   .   CALLFUNC-list\r\n.   .   .   .   AS l(16) \r\n.   .   .   .   .   INDREG-SP l(16) runtime.typ\u00b72 G0 PTR64-*byte\r\n.   .   .   .   .   ADDR l(16) PTR64-*uint8\r\n.   .   .   .   .   .   NAME-type.*\"\".T l(11) uint8\r\n\r\n.   .   .   .   AS l(16)\r\n.   .   .   .   .   INDREG-SP l(16) runtime.typ2\u00b73 G0 PTR64-*byte\r\n.   .   .   .   .   ADDR l(16) PTR64-*uint8\r\n.   .   .   .   .   .   NAME-type.\"\".I l(16) uint8\r\n\r\n.   .   .   .   AS l(16) \r\n.   .   .   .   .   INDREG-SP l(16) runtime.cache\u00b74 G0 PTR64-*PTR64-*byte\r\n.   .   .   .   .   ADDR l(16) PTR64-*PTR64-*uint8\r\n.   .   .   .   .   .   NAME-go.itab.*\"\".T.\"\".I l(16) PTR64-*uint8\r\nAS l(16) \r\n.   NAME-main.i l(16) main.I\r\n.   EFACE l(16) main.I\r\n.   .   NAME-main.autotmp_0003 l(16) PTR64-*uint8\r\n.   .   NAME-main.autotmp_0000 l(16) PTR64-*main.T<\/pre>\n<p>As you can see from the output, the compiler first adds an initialization node list (<code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">AS-init<\/code>) to the assignment node. Inside the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">AS-init<\/code> node, it creates a new variable, <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">main.autotmp_0003<\/code>, and assigns the value of the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">go.itab.*\"\".T.\"\".I<\/code> variable to it. After that, it checks whether this variable is nil. If the variable is nil, the compiler calls the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">runtime.typ2Itab<\/code> function and passes the following input to it.<\/p>\n<ul>\n<li>a pointer to the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">main.T<\/code> type<\/li>\n<li>a pointer to the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">main.I<\/code> interface type<\/li>\n<li>and a pointer to the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">go.itab.*\"\".T.\"\".I<\/code> variable<\/li>\n<\/ul>\n<p>From this code, it is quite evident that this variable is for caching the result of type conversion from <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">main.T<\/code> to <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">main.I<\/code>.<\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Inside_the_getitab_method\"><\/span>Inside the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">getitab<\/code> method<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>The next logical step is to find <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">runtime.typ2Itab<\/code>. Below is the listing of this function.<\/p>\n<pre style=\"padding-left:20px;\">func typ2Itab(t *_type, inter *interfacetype, cache **itab) *itab {\r\n\ttab := getitab(inter, t, false)\r\n\tatomicstorep(unsafe.Pointer(cache), unsafe.Pointer(tab))\r\n\treturn tab\r\n}<\/pre>\n<p>It is quite evident that the actual work is done inside the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">getitab<\/code> method, because the second line simply stores the created <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">tab<\/code> variable in the cache. So, let\u2019s look inside <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">getitab<\/code>. Since it is rather big, we only copied the most valuable part.<\/p>\n<pre style=\"padding-left:20px;\">m = \r\n    (*itab)(persistentalloc(unsafe.Sizeof(itab{})+uintptr(len(inter.mhdr)-1)*ptrSize, 0,\r\n    &amp;memstats.other_sys))\r\n    m.inter = interm._type = typ\r\n\r\nni := len(inter.mhdr)\r\nnt := len(x.mhdr)\r\nj := 0\r\nfor k := 0; k &lt; ni; k++ {\r\n\ti := &amp;inter.mhdr[k]\r\n\tiname := i.name\r\n\tipkgpath := i.pkgpath\r\n\titype := i._type\r\n\tfor ; j &lt; nt; j++ {\r\n\t\tt := &amp;x.mhdr[j]\r\n\t\tif t.mtyp == itype &amp;&amp; t.name == iname &amp;&amp; t.pkgpath == ipkgpath {\r\n\t\t\tif m != nil {\r\n\t\t\t\t*(*unsafe.Pointer)(add(unsafe.Pointer(&amp;m.fun[0]), uintptr(k)*ptrSize)) = t.ifn\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}<\/pre>\n<p>First, we allocate memory for the result.<\/p>\n<pre style=\"padding-left: 20px;\">(*itab)(persistentalloc(unsafe.Sizeof(itab{})+uintptr(len(inter.mhdr)-1)*ptrSize, 0, &amp;memstats.other_sys))<\/pre>\n<p>Why should we allocate memory in Go and why is this done in such a strange way? To answer this question, we need to look at the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">itab<\/code> struct definition.<\/p>\n<pre style=\"padding-left:20px;\">type itab struct {\r\n\tinter  *interfacetype\r\n\t_type  *_type\r\n\tlink   *itab\r\n\tbad    int32\r\n\tunused int32\r\n\tfun    [1]uintptr \/\/ variable sized\r\n}<\/pre>\n<p>The last property, <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">fun<\/code>, is defined as an array of a single element, but it is actually variable-sized. Later, we\u2019ll see that this property contains an array of pointers to methods defined in a particular type. These methods correspond to the methods in the interface type. The authors of Go use dynamic memory allocation for this property (yes, such things are possible, when you use an unsafe package). The amount of memory to be allocated is calculated by adding the size of the struct itself to the number of methods in the interface multiplied by a pointer size.<\/p>\n<pre style=\"padding-left:20px;\">unsafe.Sizeof(itab{})+uintptr(len(inter.mhdr)-1)*ptrSize<\/pre>\n<p>Next, you can see two nested loops. First, we iterate through all interface methods. For each method in the interface, we try to find a corresponding method in a particular type (the methods are stored in the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">mhdr<\/code> collection). The process of checking whether two methods are equal is quite self-explanatory.<\/p>\n<pre style=\"padding-left:20px;\">if t.mtyp == itype &amp;&amp; t.name == iname &amp;&amp; t.pkgpath == ipkgpath<\/pre>\n<p>If we find a match, we store a pointer to the method in the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">fun<\/code> property of the result.<\/p>\n<pre style=\"padding-left:20px;\">*(*unsafe.Pointer)(add(unsafe.Pointer(&amp;m.fun[0]), uintptr(k)*ptrSize)) = t.ifn<\/pre>\n<p>A small note on performance: since methods are sorted alphabetically for interface and pre-set type definitions, this nested loop can repeat <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">O(n + m)<\/code> times instead of <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">O(n * m)<\/code> times, where <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">n<\/code> and <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">m<\/code> correspond to the number of methods.<\/p>\n<p>Finally, do you remember the last part of the assignment?<\/p>\n<pre style=\"padding-left: 20px;\">AS l(16) \r\n.   NAME-main.i l(16) main.I\r\n.   EFACE l(16) main.I\r\n.   .   NAME-main.autotmp_0003 l(16) PTR64-*uint8\r\n.   .   NAME-main.autotmp_0000 l(16) PTR64-*main.T<\/pre>\n<p>Here, we assign the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">EFACE<\/code> node to the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">main.i<\/code> variable. This node (<code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">EFACE<\/code>) contains references to the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">main.autotmp_0003<\/code> variable\u2014a pointer to the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">itab<\/code> struct that was returned by the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">runtime.typ2Itab<\/code> method\u2014and to the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">autotmp_0000<\/code> variable that contains the same value as the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">main.t<\/code> variable. This is all we need to call methods by interface references.<\/p>\n<p>So, the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">main.i<\/code> variable contains an instance of the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">iface<\/code> struct defined in the runtime package.<\/p>\n<pre style=\"padding-left:20px;\">type iface struct {\r\n\ttab  *itab\r\n\tdata unsafe.Pointer\r\n}<\/pre>\n<p>We understand that we\u2019ve only covered a very small part of the Go compiler and the Go runtime so far. There are still plenty of interesting things to talk about, such as object files, the linker, relocations, etc. These will be overviewed in the upcoming blog posts.<\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Further_reading\"><\/span>Further reading<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<ul>\n<li><a href=\"https:\/\/www.altoros.com\/blog\/golang-internals-part-1-main-concepts-and-project-structure\/\">Golang Internals, Part 1: Main Concepts and Project Structure<\/a><\/li>\n<li><a href=\"https:\/\/www.altoros.com\/blog\/golang-internals-part-3-the-linker-object-files-and-relocations\/\">Golang Internals, Part 3: The Linker, Object Files, and Relocations<\/a><\/li>\n<li><a href=\"https:\/\/www.altoros.com\/blog\/golang-internals-part-4-object-files-and-function-metadata\/\">Golang Internals, Part 4: Object Files and Function Metadata<\/a><\/li>\n<li><a href=\"https:\/\/www.altoros.com\/blog\/golang-internals-part-5-the-runtime-bootstrap-process\/\">Golang Internals, Part 5: the Runtime Bootstrap Process<\/a><\/li>\n<li><a href=\"https:\/\/www.altoros.com\/blog\/golang-internals-part-6-bootstrapping-and-memory-allocator-initialization\/\">Golang Internals, Part 6: Bootstrapping and Memory Allocator Initialization<\/a><\/li>\n<\/ul>\n<hr \/>\n<p><center><small>This post was written by <b>Siarhei Matsiukevich<\/b> and edited by <a href=\"https:\/\/www.altoros.com\/blog\/author\/sophie.turol\/\">Sophia Turol<\/a> and <a href=\"https:\/\/www.altoros.com\/blog\/author\/alex\/\">Alex Khizhniak<\/a>.<\/small><\/center><\/p>\n","protected":false},"excerpt":{"rendered":"<p>All parts: Part 1 | Part 2 | Part 3 | Part 4 | Part 5 | Part 6<\/p>\n<p>&nbsp;<\/p>\n<\/p>\n<p>Do you know what exactly happens in the Go runtime, when you use a variable via interface reference? This is not a trivial question, because in Go a type that implements an [&#8230;]<\/p>\n","protected":false},"author":94,"featured_media":47335,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"content-type":"","footnotes":"","_links_to":"","_links_to_target":""},"categories":[214],"tags":[895],"class_list":["post-47322","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorials","tag-research-and-development"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.6 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Golang Internals, Part 2: Diving Into the Go Compiler | Altoros<\/title>\n<meta name=\"description\" content=\"Using a sample Go program, this blog post explains how a node tree is generated and utilized.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.altoros.com\/blog\/golang-internals-part-2-diving-into-the-go-compiler\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Golang Internals, Part 2: Diving Into the Go Compiler | Altoros\" \/>\n<meta property=\"og:description\" content=\"All parts: Part 1 | Part 2 | Part 3 | Part 4 | Part 5 | Part 6 &nbsp; Do you know what exactly happens in the Go runtime, when you use a variable via interface reference? This is not a trivial question, because in Go a type that implements an [...]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.altoros.com\/blog\/golang-internals-part-2-diving-into-the-go-compiler\/\" \/>\n<meta property=\"og:site_name\" content=\"Altoros\" \/>\n<meta property=\"article:published_time\" content=\"2015-03-05T14:33:02+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2019-11-27T15:06:39+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2015\/03\/golang-internals-part-2-diving-into-the-go-compiler.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1024\" \/>\n\t<meta property=\"og:image:height\" content=\"768\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Siarhei Matsiukevich\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Siarhei Matsiukevich\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.altoros.com\/blog\/golang-internals-part-2-diving-into-the-go-compiler\/\",\"url\":\"https:\/\/www.altoros.com\/blog\/golang-internals-part-2-diving-into-the-go-compiler\/\",\"name\":\"Golang Internals, Part 2: Diving Into the Go Compiler | Altoros\",\"isPartOf\":{\"@id\":\"https:\/\/www.altoros.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.altoros.com\/blog\/golang-internals-part-2-diving-into-the-go-compiler\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.altoros.com\/blog\/golang-internals-part-2-diving-into-the-go-compiler\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2015\/03\/golang-internals-part-2-diving-into-the-go-compiler.png\",\"datePublished\":\"2015-03-05T14:33:02+00:00\",\"dateModified\":\"2019-11-27T15:06:39+00:00\",\"author\":{\"@id\":\"https:\/\/www.altoros.com\/blog\/#\/schema\/person\/5c29ff93db657e3cf6552d5e642003d9\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.altoros.com\/blog\/golang-internals-part-2-diving-into-the-go-compiler\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.altoros.com\/blog\/golang-internals-part-2-diving-into-the-go-compiler\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.altoros.com\/blog\/golang-internals-part-2-diving-into-the-go-compiler\/#primaryimage\",\"url\":\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2015\/03\/golang-internals-part-2-diving-into-the-go-compiler.png\",\"contentUrl\":\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2015\/03\/golang-internals-part-2-diving-into-the-go-compiler.png\",\"width\":1024,\"height\":768},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.altoros.com\/blog\/golang-internals-part-2-diving-into-the-go-compiler\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.altoros.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Golang Internals, Part 2: Diving Into the Go Compiler\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.altoros.com\/blog\/#website\",\"url\":\"https:\/\/www.altoros.com\/blog\/\",\"name\":\"Altoros\",\"description\":\"Insight\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.altoros.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.altoros.com\/blog\/#\/schema\/person\/5c29ff93db657e3cf6552d5e642003d9\",\"name\":\"Siarhei Matsiukevich\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.altoros.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2016\/06\/Sergey-Matyukevich-150x150.jpg\",\"contentUrl\":\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2016\/06\/Sergey-Matyukevich-150x150.jpg\",\"caption\":\"Siarhei Matsiukevich\"},\"description\":\"Siarhei Matsiukevich is a Cloud Engineer and Go Developer at Altoros. With 6+ years in software engineering, he is an expert in cloud automation and designing architectures for complex cloud-based systems. An active member of the Go community, Siarhei is a frequent contributor to open-source projects, such as Ubuntu and Juju Charms.\",\"url\":\"https:\/\/www.altoros.com\/blog\/author\/siarhei-matsiukevich\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Golang Internals, Part 2: Diving Into the Go Compiler | Altoros","description":"Using a sample Go program, this blog post explains how a node tree is generated and utilized.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.altoros.com\/blog\/golang-internals-part-2-diving-into-the-go-compiler\/","og_locale":"en_US","og_type":"article","og_title":"Golang Internals, Part 2: Diving Into the Go Compiler | Altoros","og_description":"All parts: Part 1 | Part 2 | Part 3 | Part 4 | Part 5 | Part 6 &nbsp; Do you know what exactly happens in the Go runtime, when you use a variable via interface reference? This is not a trivial question, because in Go a type that implements an [...]","og_url":"https:\/\/www.altoros.com\/blog\/golang-internals-part-2-diving-into-the-go-compiler\/","og_site_name":"Altoros","article_published_time":"2015-03-05T14:33:02+00:00","article_modified_time":"2019-11-27T15:06:39+00:00","og_image":[{"width":1024,"height":768,"url":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2015\/03\/golang-internals-part-2-diving-into-the-go-compiler.png","type":"image\/png"}],"author":"Siarhei Matsiukevich","twitter_misc":{"Written by":"Siarhei Matsiukevich","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.altoros.com\/blog\/golang-internals-part-2-diving-into-the-go-compiler\/","url":"https:\/\/www.altoros.com\/blog\/golang-internals-part-2-diving-into-the-go-compiler\/","name":"Golang Internals, Part 2: Diving Into the Go Compiler | Altoros","isPartOf":{"@id":"https:\/\/www.altoros.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.altoros.com\/blog\/golang-internals-part-2-diving-into-the-go-compiler\/#primaryimage"},"image":{"@id":"https:\/\/www.altoros.com\/blog\/golang-internals-part-2-diving-into-the-go-compiler\/#primaryimage"},"thumbnailUrl":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2015\/03\/golang-internals-part-2-diving-into-the-go-compiler.png","datePublished":"2015-03-05T14:33:02+00:00","dateModified":"2019-11-27T15:06:39+00:00","author":{"@id":"https:\/\/www.altoros.com\/blog\/#\/schema\/person\/5c29ff93db657e3cf6552d5e642003d9"},"breadcrumb":{"@id":"https:\/\/www.altoros.com\/blog\/golang-internals-part-2-diving-into-the-go-compiler\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.altoros.com\/blog\/golang-internals-part-2-diving-into-the-go-compiler\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.altoros.com\/blog\/golang-internals-part-2-diving-into-the-go-compiler\/#primaryimage","url":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2015\/03\/golang-internals-part-2-diving-into-the-go-compiler.png","contentUrl":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2015\/03\/golang-internals-part-2-diving-into-the-go-compiler.png","width":1024,"height":768},{"@type":"BreadcrumbList","@id":"https:\/\/www.altoros.com\/blog\/golang-internals-part-2-diving-into-the-go-compiler\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.altoros.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Golang Internals, Part 2: Diving Into the Go Compiler"}]},{"@type":"WebSite","@id":"https:\/\/www.altoros.com\/blog\/#website","url":"https:\/\/www.altoros.com\/blog\/","name":"Altoros","description":"Insight","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.altoros.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.altoros.com\/blog\/#\/schema\/person\/5c29ff93db657e3cf6552d5e642003d9","name":"Siarhei Matsiukevich","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.altoros.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2016\/06\/Sergey-Matyukevich-150x150.jpg","contentUrl":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2016\/06\/Sergey-Matyukevich-150x150.jpg","caption":"Siarhei Matsiukevich"},"description":"Siarhei Matsiukevich is a Cloud Engineer and Go Developer at Altoros. With 6+ years in software engineering, he is an expert in cloud automation and designing architectures for complex cloud-based systems. An active member of the Go community, Siarhei is a frequent contributor to open-source projects, such as Ubuntu and Juju Charms.","url":"https:\/\/www.altoros.com\/blog\/author\/siarhei-matsiukevich\/"}]}},"_links":{"self":[{"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/posts\/47322","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/users\/94"}],"replies":[{"embeddable":true,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/comments?post=47322"}],"version-history":[{"count":14,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/posts\/47322\/revisions"}],"predecessor-version":[{"id":47845,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/posts\/47322\/revisions\/47845"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/media\/47335"}],"wp:attachment":[{"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/media?parent=47322"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/categories?post=47322"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/tags?post=47322"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}