site

personal website, served at mordaunt.dev/site
Log | Files | Refs

index.html (37918B)


      1 <!DOCTYPE html>
      2 <html lang="en">
      3 
      4 <head>
      5   <title>
      6   Why People Love to Hate Go · Jack Mordaunt
      7 </title>
      8   <meta charset="utf-8">
      9 <meta name="viewport" content="width=device-width, initial-scale=1.0">
     10 <meta name="color-scheme" content="light dark">
     11 
     12 
     13 
     14 
     15 <meta name="author" content="Jack Mordaunt">
     16 <meta name="description" content="Go has good ideas but never gives them to you completely.">
     17 <meta name="keywords" content="blog,developer,personal,software,robust,performance,sovereign">
     18 
     19 
     20 
     21   <meta name="twitter:card" content="summary">
     22   <meta name="twitter:title" content="Why People Love to Hate Go">
     23   <meta name="twitter:description" content="Go has good ideas but never gives them to you completely.">
     24 
     25 <meta property="og:url" content="http://jackmordaunt.com/posts/why-people-hate-go/">
     26   <meta property="og:site_name" content="Jack Mordaunt">
     27   <meta property="og:title" content="Why People Love to Hate Go">
     28   <meta property="og:description" content="Go has good ideas but never gives them to you completely.">
     29   <meta property="og:locale" content="en">
     30   <meta property="og:type" content="article">
     31     <meta property="article:section" content="posts">
     32     <meta property="article:published_time" content="2025-07-23T14:16:55-03:00">
     33     <meta property="article:modified_time" content="2025-07-23T14:16:55-03:00">
     34     <meta property="article:tag" content="Go">
     35     <meta property="article:tag" content="Odin">
     36 
     37 
     38 
     39 
     40 <link rel="canonical" href="http://jackmordaunt.com/posts/why-people-hate-go/">
     41 
     42 
     43 <link rel="preload" href="/fonts/fa-brands-400.woff2" as="font" type="font/woff2" crossorigin>
     44 <link rel="preload" href="/fonts/fa-regular-400.woff2" as="font" type="font/woff2" crossorigin>
     45 <link rel="preload" href="/fonts/fa-solid-900.woff2" as="font" type="font/woff2" crossorigin>
     46 
     47 
     48   
     49   
     50   <link rel="stylesheet" href="/css/coder.min.6445a802b9389c9660e1b07b724dcf5718b1065ed2d71b4eeaf981cc7cc5fc46.css" integrity="sha256-ZEWoArk4nJZg4bB7ck3PVxixBl7S1xtO6vmBzHzF/EY=" crossorigin="anonymous" media="screen" />
     51 
     52 
     53 
     54 
     55 
     56 
     57   
     58     
     59     
     60     <link rel="stylesheet" href="/css/coder-dark.min.a00e6364bacbc8266ad1cc81230774a1397198f8cfb7bcba29b7d6fcb54ce57f.css" integrity="sha256-oA5jZLrLyCZq0cyBIwd0oTlxmPjPt7y6KbfW/LVM5X8=" crossorigin="anonymous" media="screen" />
     61   
     62 
     63 
     64 
     65  
     66   
     67     
     68     <link rel="stylesheet" href="/css/custom.min.931a9d02d6f7655cd0cd50317fac1204e00c54ffd0232085acc957b2db5e1283.css" integrity="sha256-kxqdAtb3ZVzQzVAxf6wSBOAMVP/QIyCFrMlXstteEoM=" crossorigin="anonymous" media="screen" />
     69   
     70 
     71 
     72 
     73 
     74 
     75 <link rel="icon" type="image/svg+xml" href="/images/self-tiny-white.svg" sizes="any">
     76 <link rel="icon" type="image/png" href="/images/self-tiny-white.png" sizes="32x32">
     77 <link rel="icon" type="image/png" href="/images/self-tiny-white.png" sizes="16x16">
     78 
     79 <link rel="apple-touch-icon" href="/images/apple-touch-icon.png">
     80 <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon.png">
     81 
     82 <link rel="manifest" href="/site.webmanifest">
     83 <link rel="mask-icon" href="/images/safari-pinned-tab.svg" color="#5bbad5">
     84 
     85 
     86 
     87 
     88 
     89 
     90 
     91 <script defer data-domain="jackmordaunt.com" src="https://plausible.io/js/script.js"></script>
     92 
     93 
     94 
     95 
     96 </head>
     97 
     98 
     99 
    100 
    101 
    102 
    103 <body class="preload-transitions colorscheme-auto">
    104   
    105 <div class="float-container">
    106     <a id="dark-mode-toggle" class="colorscheme-toggle">
    107         <i class="fa-solid fa-adjust fa-fw" aria-hidden="true"></i>
    108     </a>
    109 </div>
    110 
    111 
    112   <main class="wrapper">
    113     <nav class="navigation">
    114   <section class="container">
    115     
    116     <a class="navigation-title" href="http://jackmordaunt.com/">
    117       Jack Mordaunt
    118     </a>
    119     
    120     
    121       <input type="checkbox" id="menu-toggle" />
    122       <label class="menu-button float-right" for="menu-toggle">
    123         <i class="fa-solid fa-bars fa-fw" aria-hidden="true"></i>
    124       </label>
    125       <ul class="navigation-list">
    126         
    127           
    128             <li class="navigation-item">
    129               <a class="navigation-link " href="/posts/">Blog</a>
    130             </li>
    131           
    132             <li class="navigation-item">
    133               <a class="navigation-link " href="/about/">About</a>
    134             </li>
    135           
    136             <li class="navigation-item">
    137               <a class="navigation-link " href="/projects/">Projects</a>
    138             </li>
    139           
    140             <li class="navigation-item">
    141               <a class="navigation-link " href="/contact/">Contact</a>
    142             </li>
    143           
    144             <li class="navigation-item">
    145               <a class="navigation-link " href="/pay-with-bitcoin/">Pay</a>
    146             </li>
    147           
    148         
    149         
    150       </ul>
    151     
    152   </section>
    153 </nav>
    154 
    155 
    156     <div class="content">
    157       
    158   <section class="container post">
    159     <article>
    160       <header>
    161         <div class="post-title">
    162           <h1 class="title">
    163             <a class="title-link" href="http://jackmordaunt.com/posts/why-people-hate-go/">
    164               Why People Love to Hate Go
    165             </a>
    166           </h1>
    167         </div>
    168         <div class="post-meta">
    169           <div class="date">
    170             <span class="posted-on">
    171               <i class="fa-solid fa-calendar" aria-hidden="true"></i>
    172               <time datetime="2025-07-23T14:16:55-03:00">
    173                 July 23, 2025
    174               </time>
    175             </span>
    176             <span class="reading-time">
    177               <i class="fa-solid fa-clock" aria-hidden="true"></i>
    178               9-minute read
    179             </span>
    180           </div>
    181           <div class="authors">
    182   <i class="fa-solid fa-user" aria-hidden="true"></i>
    183     <a href="/authors/jack-mordaunt/">Jack Mordaunt</a></div>
    184 
    185           <div class="categories">
    186   <i class="fa-solid fa-folder" aria-hidden="true"></i>
    187     <a href="/categories/development/">Development</a>
    188       <span class="separator">•</span>
    189     <a href="/categories/opinion/">Opinion</a></div>
    190 
    191           <div class="tags">
    192   <i class="fa-solid fa-tag" aria-hidden="true"></i>
    193     <span class="tag">
    194       <a href="/tags/go/">Go</a>
    195     </span>
    196       <span class="separator">•</span>
    197     <span class="tag">
    198       <a href="/tags/odin/">Odin</a>
    199     </span></div>
    200 
    201         </div>
    202       </header>
    203 
    204       <div class="post-content">
    205         
    206         <blockquote>
    207 <p>Go is very idiosyncratic, approximating good ideas and relying heavily on data transposition.</p></blockquote>
    208 <p>In this opinion article I will higlight why I think people love to hate Go.</p>
    209 <p>I&rsquo;ll do so by contrasting Go to Odin. Odin serves as an excellent comparison because the
    210 syntax is similar in essence (both heavily inspired by Pascal and C).</p>
    211 <p>Unlike Go, Odin actually gives you the good ideas in their completeness -
    212 without a complex type system or giving up any control, and without needing to
    213 fight the ideas for a decade only to finally concede.</p>
    214 <p>This opinion is not a knock against Go authors, or community of which I respect and have
    215 been a part for a long time.</p>
    216 <p>Modern versions of Go have addressed most of the examples highlighted here.
    217 This serves to reinforce the underlying of the article: that these things
    218 are valuable, proven by the fact that Go eventually conceded on them.</p>
    219 <ul>
    220 <li>Go now has generics</li>
    221 <li>Go now has iterators</li>
    222 <li>Go now has an <code>any</code> alias that is more clear naming than <code>interface{}</code></li>
    223 </ul>
    224 <p>What follows is not an exhaustive list, but rather just highlights to frame the point being made.</p>
    225 <h2 id="generics-for-me-but-not-for-thee">
    226   Generics for Me but Not for Thee
    227   <a class="heading-link" href="#generics-for-me-but-not-for-thee">
    228     <i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"></i>
    229     <span class="sr-only">Link to heading</span>
    230   </a>
    231 </h2>
    232 <blockquote>
    233 <p>Now, time to beat the horse some more.</p></blockquote>
    234 <p>Generics: when the relationship <em>between</em> data is the thing you are trying to
    235 encode, not the shape of the data itself.</p>
    236 <h3 id="go">
    237   Go
    238   <a class="heading-link" href="#go">
    239     <i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"></i>
    240     <span class="sr-only">Link to heading</span>
    241   </a>
    242 </h3>
    243 <p>For the longest time Go had no user-level generics.</p>
    244 <p>It did have generics, but only for the runtime!</p>
    245 <p>This is ironic, because it proves the utility of generics while at the very same
    246 time denying it to the user.</p>
    247 <p>Go has relied heavily on the transpositional nature of data, using one form to represent another.
    248 It graces you with the most important structures, which alleviates the problem:</p>
    249 <ul>
    250 <li>array</li>
    251 <li>pointer</li>
    252 <li>map</li>
    253 <li>slice            (dynamic array)</li>
    254 <li>channel          (thread-safe queue)</li>
    255 <li>closure          (anonymous function)</li>
    256 <li>multiple-returns (pseudo tuple)</li>
    257 </ul>
    258 <p>In many cases you can rely on what I dub &ldquo;lexical generics&rdquo;, function closures that capture
    259 lexical values implicitly capture their types as well - making closures highly type-generic
    260 in a fascinating way. You will see this be {ab,}used in many Go codebases.</p>
    261 <p>Often the friction of custom data structures is high enough that the desired data structure
    262 will be transposed onto the runtime data structures.</p>
    263 <p>Do you want a queue or stack? Use a slice.
    264 Do you want an iterator? Use a channel.
    265 Do you want a set or graph? Use a map.
    266 Do you want an enum? Use an integer.
    267 Do you want a tagged union? Use an integer kind and a fat struct.</p>
    268 <p>As you can imagine these choices can come with significant penalties. Using a channel as
    269 an iterator, simply because it is both type-generic and integrates with the looping syntax, adds
    270 performance overhead due to its thread safety properties. If you don&rsquo;t need threadsafety, you&rsquo;re
    271 needlessly paying for it anyway, just to coerce the language into being ergonomic to you.</p>
    272 <p>It&rsquo;s not a virtue to rely on the transpositional nature of data structures to avoid generics,
    273 but this was the underlying argument for &ldquo;why do you even need generics?&rdquo;.
    274 The true formulation is more like &ldquo;we have given you enough generic structures,
    275 just transpose onto them&rdquo;.</p>
    276 <p>Go never really told you that generics was not needed, only that it had provided enough already.</p>
    277 <h3 id="odin">
    278   Odin
    279   <a class="heading-link" href="#odin">
    280     <i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"></i>
    281     <span class="sr-only">Link to heading</span>
    282   </a>
    283 </h3>
    284 <p>Odin gives you parametric polymorphism: a simple form of generics that allows for the building of
    285 type-safe, generic data structures. It is &ldquo;simple&rdquo; because it doesn&rsquo;t come with a lot of features
    286 or baggage. There are no traits, no method sets, and no &ldquo;complex type system&rdquo;.</p>
    287 <p>Parametric: of parameters.
    288 Polymorphism: of many shapes.</p>
    289 <p>Put together it means &ldquo;parameter that can take on many shapes&rdquo;. The Odin
    290 community shortens this to &ldquo;parapoly&rdquo; for brevity.</p>
    291 <p>When people say they want generics, parapoly is usually what they want.</p>
    292 <p>The reality: types are a compile-time-known datum. The idea that you cannot
    293 parameterise structures and functions by a simple shape known at compile time
    294 is silly. The problem domain: not very complex. This will rhyme when we talk about
    295 dynamic types.</p>
    296 <p>The punchline: Odin gives you what you actually wanted, parametric polymorphism.
    297 It doesn&rsquo;t expect you to transpose yourself into oblivion.</p>
    298 <div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-odin" data-lang="odin"><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic">// A simple structure that cares about the relationship between T&#39;s,
    299 </span></span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic">// not the shape of T itself. Tell me, where is the complex type-system?
    300 </span></span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"></span>Node<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">::</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">struct</span>(<span style="color:#f85149">$</span>T<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">typeid</span>)<span style="color:#6e7681"> </span>{<span style="color:#6e7681">
    301 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">  </span>parent<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">^</span>T,<span style="color:#6e7681">
    302 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">  </span>child<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681">  </span><span style="color:#ff7b72;font-weight:bold">^</span>T,<span style="color:#6e7681">
    303 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681"></span>}<span style="color:#6e7681">
    304 </span></span></span></code></pre></div><h2 id="no-true-dynamic-type">
    305   No True Dynamic Type
    306   <a class="heading-link" href="#no-true-dynamic-type">
    307     <i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"></i>
    308     <span class="sr-only">Link to heading</span>
    309   </a>
    310 </h2>
    311 <blockquote>
    312 <p>Noob: How do I do dynamic typing in Go?</p>
    313 <p>Go: Here, use this: <code>interface{}</code> - it&rsquo;s called the &ldquo;empty interface&rdquo;.</p>
    314 <p>Noob: &hellip;</p>
    315 <p>Noob: Uh, what?</p>
    316 <p>Go: I wasn&rsquo;t really meant for dynamic typing, use that or structure your program differently.</p>
    317 <p>Noob: Ok fine, I&rsquo;ll use the &ldquo;empty interface&rdquo; then&hellip;</p></blockquote>
    318 <p>Dynamic programming is important and useful, it&rsquo;s also not difficult to support first-class.</p>
    319 <p>Dynamic types reduce to a fat pointer: a structure that contains two pointers,
    320 one pointing to the data and one pointing to the type information. This allows
    321 the program to handle arbitrary values at runtime by writing logic against
    322 dynamic types.</p>
    323 <p>However Go is an OOP language. It encodes the very essence of OOP: behavioural polymorpshim
    324 based on v-tables. The term used in Go for this concept is the <code>interface</code>.</p>
    325 <p>Like a true dynamic type, the interface is indeed a fat pointer:</p>
    326 <div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#ff7b72">type</span> ITab <span style="color:#ff7b72">struct</span> {
    327 </span></span><span style="display:flex;"><span>	Inter <span style="color:#ff7b72;font-weight:bold">*</span>InterfaceType
    328 </span></span><span style="display:flex;"><span>	Type  <span style="color:#ff7b72;font-weight:bold">*</span>Type
    329 </span></span><span style="display:flex;"><span>  <span style="color:#8b949e;font-style:italic">// --snip--</span>
    330 </span></span><span style="display:flex;"><span>}
    331 </span></span></code></pre></div><p>The revealing part is the separate definition for the empty interface:</p>
    332 <div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#ff7b72">type</span> EmptyInterface <span style="color:#ff7b72">struct</span> {
    333 </span></span><span style="display:flex;"><span>	Type <span style="color:#ff7b72;font-weight:bold">*</span>Type
    334 </span></span><span style="display:flex;"><span>	Data unsafe.Pointer
    335 </span></span><span style="display:flex;"><span>}
    336 </span></span></code></pre></div><p>Why is this bothersome? Instead of just giving you an &ldquo;any&rdquo; type,
    337 Go forces you to talk in terms of &ldquo;interfaces that have no methods&rdquo;.</p>
    338 <p>Linguistically and conceptually this makes no sense.</p>
    339 <p>This is philosphically impure.</p>
    340 <p>Look at these beauties:</p>
    341 <ul>
    342 <li><code>[]interface{}</code></li>
    343 <li><code>map[interface{}]interface{}</code></li>
    344 <li><code>func(string, ...interface{})</code></li>
    345 <li><code>struct { value interface{} }</code></li>
    346 </ul>
    347 <p>A better approach is to do what Odin does: just give you the <code>any</code> type.
    348 Defined as simple as the concept is, a fat pointer.</p>
    349 <div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-odin" data-lang="odin"><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic">// Raw_Any points at some data, and associates type data with it.
    350 </span></span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic">// This type is named `any` at the user-level.
    351 </span></span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"></span>Raw_Any<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">::</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">struct</span><span style="color:#6e7681"> </span>{<span style="color:#6e7681">
    352 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">	</span>data<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">rawptr</span>,<span style="color:#6e7681">
    353 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">	</span>id<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681">   </span><span style="color:#ff7b72">typeid</span>,<span style="color:#6e7681">
    354 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681"></span>}<span style="color:#6e7681">
    355 </span></span></span></code></pre></div><p>Once you understand fat pointers, dynamic programming becomes easy.</p>
    356 <p>Now, if you want an interface in Odin, you simply define a struct that contains
    357 a pointer to the data and a pointer to the implementation procedure (rather than
    358 a typeid).</p>
    359 <p>Consider the common allocator interface:</p>
    360 <div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-odin" data-lang="odin"><span style="display:flex;"><span>Allocator<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">::</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">struct</span><span style="color:#6e7681"> </span>{<span style="color:#6e7681">
    361 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">	</span>procedure<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span>Allocator_Proc,<span style="color:#6e7681">
    362 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">	</span>data<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681">      </span><span style="color:#ff7b72">rawptr</span>,<span style="color:#6e7681">
    363 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681"></span>}<span style="color:#6e7681">
    364 </span></span></span></code></pre></div><p>It&rsquo;s the same underlying idea (with a v-table of 1 to keep it ergonomic).</p>
    365 <p>Any specialised allocator just needs to map itself onto this generic Allocator
    366 structure and voilà, you have achieved runtime behavioural polymorphism!</p>
    367 <p>Go has rectified the language-side of this in later releases, including the
    368 <code>any</code> alias (equivalent to <code>interface{}</code> in all ways), but you can see how
    369 Go&rsquo;s design doesn&rsquo;t reason up from first principles, but rather down from empiricism.</p>
    370 <blockquote>
    371 <p>We think objects are good idea.</p>
    372 <p>We want to do them at runtime.</p>
    373 <p>Aha, the interface type. It&rsquo;s a fat pointer to a vtable and some data.</p>
    374 <p>Look, if you want to do dynamic programming you can just use an empty interface!</p></blockquote>
    375 <h2 id="declaration-and-assignment-syntax">
    376   Declaration and Assignment Syntax
    377   <a class="heading-link" href="#declaration-and-assignment-syntax">
    378     <i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"></i>
    379     <span class="sr-only">Link to heading</span>
    380   </a>
    381 </h2>
    382 <p>Go and Odin both use this Pascal inspired declaration-assignment syntax <code>:=</code>.</p>
    383 <div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic">// Go</span>
    384 </span></span><span style="display:flex;"><span>
    385 </span></span><span style="display:flex;"><span><span style="color:#ff7b72">var</span> variable <span style="color:#ff7b72">string</span> = <span style="color:#a5d6ff">&#34;variable&#34;</span>
    386 </span></span><span style="display:flex;"><span><span style="color:#ff7b72">var</span> variable = <span style="color:#a5d6ff">&#34;variable&#34;</span>
    387 </span></span><span style="display:flex;"><span>
    388 </span></span><span style="display:flex;"><span><span style="color:#ff7b72">const</span> constant <span style="color:#ff7b72">string</span> = <span style="color:#a5d6ff">&#34;constant&#34;</span>
    389 </span></span><span style="display:flex;"><span><span style="color:#ff7b72">const</span> constant  = <span style="color:#a5d6ff">&#34;constant&#34;</span>
    390 </span></span><span style="display:flex;"><span>
    391 </span></span><span style="display:flex;"><span>x <span style="color:#ff7b72;font-weight:bold">:=</span> <span style="color:#a5d6ff">&#34;foobar&#34;</span>
    392 </span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-odin" data-lang="odin"><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic">// Odin
    393 </span></span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"></span><span style="color:#6e7681">
    394 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681"></span>variable<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">:=</span><span style="color:#6e7681"> </span><span style="color:#a5d6ff">&#34;variable&#34;</span><span style="color:#6e7681">
    395 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681"></span>variable<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">string</span><span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">=</span><span style="color:#6e7681"> </span><span style="color:#a5d6ff">&#34;variable&#34;</span><span style="color:#6e7681">
    396 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">
    397 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681"></span>constant<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">::</span><span style="color:#6e7681"> </span><span style="color:#a5d6ff">&#34;constant&#34;</span><span style="color:#6e7681">
    398 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681"></span>constant<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">string</span><span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span><span style="color:#a5d6ff">&#34;constant&#34;</span><span style="color:#6e7681">
    399 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">
    400 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681"></span>x<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">:=</span><span style="color:#6e7681"> </span><span style="color:#a5d6ff">&#34;foobar&#34;</span><span style="color:#6e7681">
    401 </span></span></span></code></pre></div><p>What&rsquo;s the problem? Well, the thing is that Go defines <code>:=</code> as a keyword.
    402 You cannot actually place a type between <code>:</code> and <code>=</code>.</p>
    403 <p>Once again Go fails to give you the complete idea, the grammar: <code>&lt;symbol&gt; : &lt;type&gt; = &lt;expression&gt;</code>.
    404 Where the type can be elided to result in <code>&lt;symbol&gt; := &lt;expression&gt;</code>.
    405 Where constants are the same, but with a second <code>:</code> instead of <code>=</code>.</p>
    406 <p>Go has chosen an inconsistent approach. When the underlying grammar is elegant,
    407 Go decides to take the shortcut and ignore the point. Odin just gives you the
    408 elegant, consistent grammar.</p>
    409 <p>Consider type and proc definitions:</p>
    410 <div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic">// Go</span>
    411 </span></span><span style="display:flex;"><span>
    412 </span></span><span style="display:flex;"><span><span style="color:#ff7b72">type</span> Node <span style="color:#ff7b72">struct</span> {
    413 </span></span><span style="display:flex;"><span>	<span style="color:#8b949e;font-style:italic">// --snip--</span>
    414 </span></span><span style="display:flex;"><span>}
    415 </span></span><span style="display:flex;"><span>
    416 </span></span><span style="display:flex;"><span><span style="color:#ff7b72">func</span> <span style="color:#d2a8ff;font-weight:bold">Visit</span>(n Node) {
    417 </span></span><span style="display:flex;"><span>	<span style="color:#8b949e;font-style:italic">// --snip</span>
    418 </span></span><span style="display:flex;"><span>}
    419 </span></span></code></pre></div><p>In the Go syntax we have introduced more keywords to declare types and
    420 functions. Why do we need extra syntax here? After all, struct and function
    421 definitions are just regular constants!</p>
    422 <p>In Odin, this fact is evident.</p>
    423 <div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-odin" data-lang="odin"><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic">// Odin
    424 </span></span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"></span><span style="color:#6e7681">
    425 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681"></span>node<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">::</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">struct</span><span style="color:#6e7681"> </span>{<span style="color:#6e7681">
    426 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">	</span><span style="color:#8b949e;font-style:italic">// --snip--
    427 </span></span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"></span>}<span style="color:#6e7681">
    428 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">
    429 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681"></span>visit<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">::</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">proc</span>(n<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span>node)<span style="color:#6e7681"> </span>{<span style="color:#6e7681">
    430 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">	</span><span style="color:#8b949e;font-style:italic">// --snip--
    431 </span></span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"></span>}<span style="color:#6e7681">
    432 </span></span></span></code></pre></div><p>The syntax is consistent:</p>
    433 <ul>
    434 <li>consistent with other constants</li>
    435 <li>consistently read left-to-right, with symbol first, type second, and finally the binding third</li>
    436 </ul>
    437 <p>After all, a struct defintion is a compile-time known value.
    438 Thus, the <code>node</code> type is just regular constant set to a typeid.</p>
    439 <p>Don&rsquo;t believe me? Check this out:</p>
    440 <div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-odin" data-lang="odin"><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic">// Odin
    441 </span></span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"></span><span style="color:#6e7681">
    442 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681"></span>node<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">struct</span><span style="color:#6e7681"> </span>{}<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">struct</span><span style="color:#6e7681"> </span>{<span style="color:#6e7681">
    443 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">	</span><span style="color:#8b949e;font-style:italic">// --snip--
    444 </span></span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"></span>}<span style="color:#6e7681">
    445 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">
    446 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681"></span>visit<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">proc</span>(n<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span>node)<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">proc</span>(n<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span>node)<span style="color:#6e7681"> </span>{<span style="color:#6e7681">
    447 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">	</span><span style="color:#8b949e;font-style:italic">// --snip--
    448 </span></span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"></span>}<span style="color:#6e7681">
    449 </span></span></span></code></pre></div><p>You <em>can</em> put the type in the normal type position, it&rsquo;s just elided by convention!</p>
    450 <p>And if you want them to be variables instead:</p>
    451 <div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-odin" data-lang="odin"><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic">// Odin
    452 </span></span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"></span><span style="color:#6e7681">
    453 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681"></span>node<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">struct</span><span style="color:#6e7681"> </span>{}<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">=</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">struct</span><span style="color:#6e7681"> </span>{<span style="color:#6e7681">
    454 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">	</span><span style="color:#8b949e;font-style:italic">// --snip--
    455 </span></span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"></span>}<span style="color:#6e7681">
    456 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">
    457 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681"></span>visit<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">proc</span>(n<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span>node)<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">=</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">proc</span>(n<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span>node)<span style="color:#6e7681"> </span>{<span style="color:#6e7681">
    458 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">	</span><span style="color:#8b949e;font-style:italic">// --snip--
    459 </span></span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"></span>}<span style="color:#6e7681">
    460 </span></span></span></code></pre></div><p>Odin takes the underlying idea of elegant, minimal and consistent grammar and
    461 actually just hands it to you. Type definitions are <em>just</em> constants!</p>
    462 <p>Go decides to keep the shorthand <code>:=</code> but never actually fully embraces the
    463 underlying idea. You can&rsquo;t put a type between <code>:</code> and <code>=</code>, and you are expected
    464 to use bespoke keywords for type and function declarations.</p>
    465 <p>Feel the inconsistency.</p>
    466 <div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic">// Go</span>
    467 </span></span><span style="display:flex;"><span><span style="color:#ff7b72">const</span> c <span style="color:#ff7b72">int</span> = <span style="color:#a5d6ff">42</span>
    468 </span></span><span style="display:flex;"><span><span style="color:#ff7b72">const</span> c = <span style="color:#a5d6ff">42</span>
    469 </span></span><span style="display:flex;"><span><span style="color:#ff7b72">var</span> v <span style="color:#ff7b72">int</span> = <span style="color:#a5d6ff">42</span>
    470 </span></span><span style="display:flex;"><span><span style="color:#ff7b72">var</span> v = <span style="color:#a5d6ff">42</span>
    471 </span></span><span style="display:flex;"><span>v <span style="color:#ff7b72;font-weight:bold">:=</span> <span style="color:#a5d6ff">42</span>
    472 </span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-odin" data-lang="odin"><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic">// Odin
    473 </span></span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"></span>c<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">int</span><span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span>42<span style="color:#6e7681">
    474 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681"></span>c<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">::</span><span style="color:#6e7681"> </span>42<span style="color:#6e7681">
    475 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681"></span>v<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">int</span><span style="color:#6e7681">
    476 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681"></span>v<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">int</span><span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">=</span><span style="color:#6e7681"> </span>42<span style="color:#6e7681">
    477 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681"></span>v<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">:=</span><span style="color:#6e7681"> </span>42<span style="color:#6e7681">
    478 </span></span></span></code></pre></div><h2 id="conclusion">
    479   Conclusion
    480   <a class="heading-link" href="#conclusion">
    481     <i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"></i>
    482     <span class="sr-only">Link to heading</span>
    483   </a>
    484 </h2>
    485 <p>Go develops features empirically, adopting what works practically. Odin constructs from first principles, focusing on conceptual elegance.</p>
    486 <p>Go’s incremental evolution led to ad-hoc syntax and features, making it feel less coherent to users accustomed to functional or fully featured OOP languages.</p>
    487 <p>Conversely, Odin feels purposeful and coherent, designed from foundational ideas rather than incremental adaptations.</p>
    488 <p>Despite these criticisms, Go remains practical and solid, which explains its continued popularity—and why many developers both love and hate it.</p>
    489 
    490       </div>
    491 
    492 
    493       <footer>
    494         
    495 
    496 
    497         
    498         
    499         
    500         
    501         
    502         
    503         
    504       </footer>
    505     </article>
    506 
    507     
    508   </section>
    509 
    510     </div>
    511 
    512     <footer class="footer">
    513   <section class="container">
    514     ©
    515     
    516     2025
    517      Jack Mordaunt 
    518     ·
    519     
    520     Powered by <a href="https://gohugo.io/" target="_blank" rel="noopener">Hugo</a> & <a href="https://github.com/luizdepra/hugo-coder/" target="_blank" rel="noopener">Coder</a>.
    521     
    522   </section>
    523 </footer>
    524 
    525   </main>
    526 
    527   
    528 
    529   
    530   
    531   <script src="/js/coder.min.6ae284be93d2d19dad1f02b0039508d9aab3180a12a06dcc71b0b0ef7825a317.js" integrity="sha256-auKEvpPS0Z2tHwKwA5UI2aqzGAoSoG3McbCw73gloxc="></script>
    532   
    533 
    534   
    535 
    536   
    537 
    538 
    539   
    540 
    541   
    542 
    543   
    544 
    545   
    546 
    547   
    548 
    549   
    550 
    551   
    552 
    553   
    554 
    555   
    556 
    557   
    558 
    559   
    560 
    561   
    562 
    563   
    564 
    565   
    566 
    567   
    568 
    569   
    570 
    571   
    572 </body>
    573 </html>