[{"data":1,"prerenderedAt":405},["ShallowReactive",2],{"\u002Fblogs\u002Fhow-go-interfaces-work-under-the-hood":3,"related-posts":382},{"title":4,"description":5,"coverImage":6,"timestamps":8,"body":10},"How Go Interfaces Work Under the Hood","Unpack the mechanics of Go interfaces. From memory structures to dynamic dispatch and runtime costs, learn how Golang interfaces work behind the scenes.",{"url":7,"alt":4},null,{"publishedOn":9},"2026-10-12T15:52:13+05:30",{"type":11,"value":12,"toc":372},"minimark",[13,18,33,37,110,117,167,171,296,300,322,326,353,357,368],[14,15,17],"h2",{"id":16},"_1-introduction-the-implicit-interface-philosophy","1. Introduction & The Implicit Interface Philosophy",[19,20,21,30],"ul",{},[22,23,24,25,29],"li",{},"Implicit Satisfaction: Contrast Go's duck typing at compile-time with explicit\n",[26,27,28],"code",{},"implements"," interfaces in languages like Java or C#.",[22,31,32],{},"The Core Thesis: While Go interfaces feel zero-cost and syntactic, they are\nconcrete two-pointer structs managed dynamic-dispatch machinery at runtime.",[14,34,36],{"id":35},"_2-interface-internal-structures-eface-vs-iface","2. Interface Internal Structures: eface vs. iface",[19,38,39,50,81],{},[22,40,41,42,45,46,49],{},"Explain how the Go runtime (",[26,43,44],{},"src\u002Fruntime\u002Fruntime2.go",") categorizes\n",[26,47,48],{},"interfaces"," into two distinct internal layouts:",[22,51,52,53,56,57],{},"Empty Interface (",[26,54,55],{},"eface","):",[19,58,59,70],{},[22,60,61,62,65,66,69],{},"Used for ",[26,63,64],{},"interface{}"," \u002F ",[26,67,68],{},"any",".",[22,71,72,73,76,77,80],{},"Pointer to type metadata (",[26,74,75],{},"_type",") and pointer to underlying data (",[26,78,79],{},"data",").",[22,82,83,84,56,87],{},"Non-Empty Interface (",[26,85,86],{},"iface",[19,88,89,95],{},[22,90,91,92,80],{},"Used for interfaces with methods (e.g., ",[26,93,94],{},"io.Reader",[22,96,97,98,101,102,105,106,101,108,80],{},"Consists of an ",[26,99,100],{},"itab"," pointer (",[26,103,104],{},"tab",") and ",[26,107,79],{},[26,109,79],{},[14,111,113,114,116],{"id":112},"_3-the-itab-deep-dive-interface-table","3. The ",[26,115,100],{}," Deep Dive (Interface Table)",[19,118,119,128],{},[22,120,121,122,124,125,127],{},"What is an ",[26,123,100],{},"? Explain that ",[26,126,100],{}," holds type information as well as the\nvirtual function table (vtable).",[22,129,130,131,133,134],{},"Anatomy of ",[26,132,100],{},":\n",[19,135,136,142,147,153,159],{},[22,137,138,141],{},[26,139,140],{},"inter",": Pointer to the interface type metadata.",[22,143,144,146],{},[26,145,75],{},": Pointer to the concrete type metadata.",[22,148,149,152],{},[26,150,151],{},"hash",": Copy of concrete type's hash for fast type assertions.",[22,154,155,158],{},[26,156,157],{},"fun",": Function pointer array mapping interface methods to concrete\nimplementations.",[22,160,161,163,164,166],{},[26,162,100],{}," Caching: How the runtime uses a global hash table to cache ",[26,165,100],{},"\nlookups so type conversions only pay the construction cost once.",[14,168,170],{"id":169},"_4-the-interface-equals-nil-pitfall","4. The \"Interface Equals Nil\" Pitfall",[19,172,173,187],{},[22,174,175,176,179,180,183,184,186],{},"Explain why an ",[26,177,178],{},"interface"," containing a ",[26,181,182],{},"nil"," pointer is not a ",[26,185,182],{},"\ninterface.",[22,188,189,190,193,194,197,198,200,201],{},"Show how ",[26,191,192],{},"iface.tab"," exists while ",[26,195,196],{},"iface.data"," is ",[26,199,182],{},", leading to subtle\nbugs:",[202,203,208],"pre",{"className":204,"code":205,"language":206,"meta":207,"style":207},"language-go shiki shiki-themes everforest-dark","var buf *bytes.Buffer \u002F\u002F nil pointer var r io.Reader = buf \u002F\u002F non-nil interface!\n(tab != nil, data == nil)\n\nfmt.Println(r == nil) \u002F\u002F Evaluates to FALSE\n","go","",[26,209,210,242,266,273],{"__ignoreMap":207},[211,212,215,219,223,226,230,232,235,239],"span",{"class":213,"line":214},"line",1,[211,216,218],{"class":217},"sDOmQ","var",[211,220,222],{"class":221},"sY0Nt"," buf ",[211,224,225],{"class":217},"*",[211,227,229],{"class":228},"sP-ue","bytes",[211,231,69],{"class":221},[211,233,234],{"class":228},"Buffer",[211,236,238],{"class":237},"s67c6"," \u002F\u002F nil pointer var r io.Reader = buf",[211,240,241],{"class":237}," \u002F\u002F non-nil interface!\n",[211,243,245,248,251,255,258,261,263],{"class":213,"line":244},2,[211,246,247],{"class":221},"(tab ",[211,249,250],{"class":217},"!=",[211,252,254],{"class":253},"s9lfW"," nil",[211,256,257],{"class":221},", data ",[211,259,260],{"class":217},"==",[211,262,254],{"class":253},[211,264,265],{"class":221},")\n",[211,267,269],{"class":213,"line":268},3,[211,270,272],{"emptyLinePlaceholder":271},true,"\n",[211,274,276,279,283,286,288,290,293],{"class":213,"line":275},4,[211,277,278],{"class":221},"fmt.",[211,280,282],{"class":281},"sRC7j","Println",[211,284,285],{"class":221},"(r ",[211,287,260],{"class":217},[211,289,254],{"class":253},[211,291,292],{"class":221},") ",[211,294,295],{"class":237},"\u002F\u002F Evaluates to FALSE\n",[14,297,299],{"id":298},"_5-performance-costs-escape-analysis","5. Performance Costs & Escape Analysis",[19,301,302,305],{},[22,303,304],{},"Indirect Method Calls: Why dynamic dispatch via function pointers disables\ncompiler inlining.",[22,306,307,308],{},"Heap Allocations (Escape Analysis):\n",[19,309,310,313,319],{},[22,311,312],{},"How converting values to interfaces often causes values to escape to the\nheap.",[22,314,315,316,69],{},"Pointer boxing: Primitive values or structs wrapped in ",[26,317,318],{},"unsafe.Pointer",[22,320,321],{},"Benchmarks: Show a quick benchmark comparing direct method calls vs.\ninterface dynamic calls.",[14,323,325],{"id":324},"_6-type-assertions-type-switches-mechanics","6. Type Assertions & Type Switches Mechanics",[19,327,328,343],{},[22,329,330,331,334,335,337,338,340,341,69],{},"How ",[26,332,333],{},"val.(T)"," checks type matching using the ",[26,336,151],{}," field in ",[26,339,100],{}," or\n",[26,342,75],{},[22,344,345,346,65,349,352],{},"The runtime function ",[26,347,348],{},"assertE2I",[26,350,351],{},"assertI2I"," mechanics.",[14,354,356],{"id":355},"_7-practical-engineering-takeaways","7. Practical Engineering Takeaways",[19,358,359,362,365],{},[22,360,361],{},"Accept Interfaces, Return Structs: Why this idiom prevents unnecessary heap\nallocations and abstraction leaks.",[22,363,364],{},"Keep Interfaces Small: Single-method interfaces (io.Reader, fmt.Stringer)\nmaximize reuse and keep itab tables lean.",[22,366,367],{},"Hot-Path Optimization: When to avoid interfaces in performance-critical inner\nloops to preserve inlining and zero-allocation guarantees.",[369,370,371],"style",{},"html pre.shiki code .sDOmQ, html code.shiki .sDOmQ{--shiki-default:#E69875}html pre.shiki code .sY0Nt, html code.shiki .sY0Nt{--shiki-default:#D3C6AA}html pre.shiki code .sP-ue, html code.shiki .sP-ue{--shiki-default:#7FBBB3}html pre.shiki code .s67c6, html code.shiki .s67c6{--shiki-default:#859289;--shiki-default-font-style:italic}html pre.shiki code .s9lfW, html code.shiki .s9lfW{--shiki-default:#D699B6}html pre.shiki code .sRC7j, html code.shiki .sRC7j{--shiki-default:#A7C080}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":207,"searchDepth":244,"depth":244,"links":373},[374,375,376,378,379,380,381],{"id":16,"depth":244,"text":17},{"id":35,"depth":244,"text":36},{"id":112,"depth":244,"text":377},"3. The itab Deep Dive (Interface Table)",{"id":169,"depth":244,"text":170},{"id":298,"depth":244,"text":299},{"id":324,"depth":244,"text":325},{"id":355,"depth":244,"text":356},[383,392,396],{"path":384,"title":385,"timestamps":386,"description":388,"coverImage":389},"\u002Fblogs\u002Fcreate-custom-neovim-keybindings-using-lua","How to Create Custom Keymaps in Neovim v0.12 With Lua",{"publishedOn":387},"2021-11-10T00:00:00+00:00","Deep dive into Neovim keymap configuration using Lua. Explore vim.keymap.set(), mode handling, and extensible patterns for building maintainable and ergonomic editor workflows.",{"url":390,"alt":391},"https:\u002F\u002Fik.imagekit.io\u002Fjarmos\u002Fcreating-neovim-keymaps-using-lua.png?updatedAt=1702974989266","How to create custom keymaps in Neovim with Lua?",{"path":393,"title":4,"timestamps":394,"description":5,"coverImage":395},"\u002Fblogs\u002Fhow-go-interfaces-work-under-the-hood",{"publishedOn":9},{"url":7,"alt":4},{"path":397,"title":398,"timestamps":399,"description":401,"coverImage":402},"\u002Fblogs\u002Fstandard-cicd-pipeline-for-python-projects","A Standard & Complete CI\u002FCD Pipeline for Most Python Projects",{"publishedOn":400},"2021-01-22T00:00:00+00:00","Streamline Python project CI\u002FCD with a GitHub Actions workflow. Overcome Poetry and virtual environment challenges. Achieve linting, testing, dependency caching, and CodeCov integration with minimal setup. Boost productivity and maintain code quality effortlessly.",{"url":403,"alt":404},"https:\u002F\u002Fik.imagekit.io\u002Fjarmos\u002Fstandard-cicd-pipeline-for-python-projects.png?updatedAt=1702974989270","A standard & complete CI\u002FCD pipeline for most Python projects",1792384186313]