[{"data":1,"prerenderedAt":408},["ShallowReactive",2],{"\u002Fdrafts\u002Fhow-go-interfaces-work-under-the-hood":3,"further-reading":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,400],{"path":384,"title":385,"timestamps":386,"description":388,"coverImage":389},"\u002Fblogs\u002Fbuilding-cli-apps-with-argparse-from-the-standard-library","Building CLI applications with Python's argparse module.",{"publishedOn":387},"2025-11-12T16:50:04+00:00","A step-by-step guide to creating Python CLI applications with argparse. Parse\narguments, generate files, and automate tasks using only the standard library.\n",{"url":390,"alt":391},"https:\u002F\u002Fik.imagekit.io\u002Fjarmos\u002Fbuilding-cli-apps-with-argparse.png?updatedAt=1763202236560","Building CLI apps with Python standard library modules",{"path":393,"title":394,"timestamps":395,"description":397,"coverImage":398},"\u002Fblogs\u002Fusing-github-actions-to-deploy-to-heroku","Using GitHub Actions to Deploy a FastAPI Project to Heroku",{"publishedOn":396},"2021-05-05T00:00:00+00:00","Deploy FastAPI projects to Heroku seamlessly using GitHub Actions. Avoid Heroku CLI and extra dependencies. Configure CI\u002FCD pipeline with GitHub Actions, ensuring quality standards and last-line-of-defense health-checks. Detailed steps, potential roadblocks, and alternatives discussed.",{"url":399,"alt":394},"https:\u002F\u002Fik.imagekit.io\u002Fjarmos\u002Fusing-github-actions-to-deploy-to-heroku.png?updatedAt=1702974989351",{"path":401,"title":402,"timestamps":403,"description":405,"coverImage":406},"\u002Fblogs\u002Fa-deep-dive-into-go-compile-time-interface-assertions","A Deep Dive Into Go's Compile-Time Interface Assertions",{"publishedOn":404},"2026-06-18T12:06:41+00:00","Learn how pointers work in Go with clear explanations and practical examples. This guide covers pointer types, memory addresses, dereferencing and why pointers matter for writing efficient and reliable Go programs.",{"url":407,"alt":402},"https:\u002F\u002Fik.imagekit.io\u002Fjarmos\u002Fa-deep-dive-into-go-compile-time-interface-assertions.png",1791802305215]