<rss version="2.0">
  <channel>
    <title>Golang on Leon Mika</title>
    <link>https://lmika.org/categories/golang/</link>
    <description></description>
    
    <language>en</language>
    
    <lastBuildDate>Tue, 11 Aug 2026 08:43:45 +1000</lastBuildDate>
    
    <item>
      <title></title>
      <link>https://lmika.org/2026/08/11/the-most-common-integer-type.html</link>
      <pubDate>Tue, 11 Aug 2026 08:43:45 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2026/08/11/the-most-common-integer-type.html</guid>
      <description>&lt;p&gt;The most common integer type in Go is &lt;code&gt;int&lt;/code&gt;, and 90% of the time, it should be the one to use. There are some QoL issues with using &lt;code&gt;uint&lt;/code&gt;: values show up as hex in the debugger, linter complains about overflows. A 64 bit unsigned int is overkill for a retry count that&amp;rsquo;s likely to be less than 10.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Musings Of Faking a REST-API Client in Server-Side Rendered Templates</title>
      <link>https://lmika.org/2026/07/24/musings-of-faking-a-restapi.html</link>
      <pubDate>Fri, 24 Jul 2026 10:43:11 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2026/07/24/musings-of-faking-a-restapi.html</guid>
      <description>&lt;p&gt;One of the arguments proponents have against server-side rendering is that you can have a well-defined API that would work for both your web frontend and things like a mobile client. It&amp;rsquo;s a good argument, and it got me wondering if it&amp;rsquo;s possible to do this with server-side templates too.&lt;/p&gt;
&lt;p&gt;What I&amp;rsquo;m imagining is a series of Go handlers powering the API, and another series of Go handlers that simply serve templates, all being served by one app. These templates would have what look like HTTP calls, like &amp;ldquo;get&amp;rdquo; and &amp;ldquo;post&amp;rdquo;, but in the background, will simply call the API handlers with a &amp;ldquo;fake&amp;rdquo; HTTP request. It would look like REST calls from the templates, but under the hood, it would be handers calling handlers directly, without a network round-trip.&lt;/p&gt;
&lt;p&gt;If you imagine, for example, an API for getting a list of support tickets, maybe with the following REST calls:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;GET /tickets/&lt;/code&gt; - list all tickets with an optional search query&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /tickets/{:id}&lt;/code&gt; - get details of a single ticket&lt;/li&gt;
&lt;li&gt;&lt;code&gt;POST /tickets/&lt;/code&gt; - create a new ticket&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Then, if you want to build a homepage showing the user&amp;rsquo;s currently assigned tickets, you could build a Go template like the following:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&amp;lt;h1&amp;gt;My tickets&amp;lt;/h1&amp;gt;

{{ $tickets := get &amp;#34;/tickets?owner=me&amp;#34; }}
{{ range $tickets }}
   &amp;lt;!-- Render tickets as HTML here --&amp;gt;
{{ end }}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That &lt;code&gt;get&lt;/code&gt; call will appear like a HTTP request, but could simply be a &lt;a href=&#34;https://pkg.go.dev/net/http#Request&#34;&gt;http.Request&lt;/a&gt; created in memory, and sent directly to the handler via the &lt;a href=&#34;https://pkg.go.dev/net/http#Handler&#34;&gt;ServeHTTP&lt;/a&gt; method. No need for a server round-trip, and you get the benefits of having a well-defined API along with the flexibility of a frontend that will use that API to the extent that it needs to.&lt;/p&gt;
&lt;p&gt;It could potentially work with posts too. For example, the template accepting the form inputs for a new ticket:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;{{ $myData := .FormData }}
{{ $res := post &amp;#34;/tickets&amp;#34; $myData }}
{{ send_redirect &amp;#34;/&amp;#34; }}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This does look a bit like PHP to my eyes if I&amp;rsquo;m being honest. I&amp;rsquo;m guessing you&amp;rsquo;ll need a pretty decent templating language to support this, but this wouldn&amp;rsquo;t be a problem for Go&amp;rsquo;s template.&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Not entirely sure why you&amp;rsquo;d would choose this route over simply rendering the templates in the handler. Since they&amp;rsquo;re in the same memory space, there&amp;rsquo;s nothing stopping you from simply passing domain models around. One argument might be that this will force you to have a well-defined API that you yourself are using. Another might be that should you ever want to split your system into an API and HTTP frontend, it would easy to do so: simply take the handlers serving these templates and place them in a separate binary. Naturally this all depends on how separate you&amp;rsquo;re keeping the two, so some discipline in making sure the two sets of handlers are isolated might be needed if this is a possibility.&lt;/p&gt;
&lt;p&gt;You will loose niceties like having a path serving both an API and frontend (although, with proper content negotiation you can probably get away with it), and yeah, we are still talking about server-side rendering, so no virtual DOMs or all that &amp;ldquo;niceties&amp;rdquo; that come from React US. Even so, might be worth exploring as a technique for a small project, just to see how it feels.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;Or an embedded PHP runtime, if you&amp;rsquo;re feeling adventurous.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2026/07/06/til-that-gos-formatter-will.html</link>
      <pubDate>Mon, 06 Jul 2026 15:26:28 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2026/07/06/til-that-gos-formatter-will.html</guid>
      <description>&lt;p&gt;TIL that Go&amp;rsquo;s formatter will be fine formatting a file with a composite literal for a slice, yet the Golang CI linter will complain about it and simply say the file is not fomatted:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// gofmt will be fine with this, but not golangci-lint&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;myValues&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; []&lt;span style=&#34;color:#a6e22e&#34;&gt;myType&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;myType&lt;/span&gt;{ &lt;span style=&#34;color:#a6e22e&#34;&gt;Foo&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;Bar&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;myType&lt;/span&gt;{ &lt;span style=&#34;color:#a6e22e&#34;&gt;Foo&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;Bar&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So when you find you find yourself seeing a linter complain that a file that&amp;rsquo;s not formatted when it seems to be (maybe via an auto-format on save feature), try removing the redundant type name:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;myValues&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; []&lt;span style=&#34;color:#a6e22e&#34;&gt;myType&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; { &lt;span style=&#34;color:#a6e22e&#34;&gt;Foo&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;Bar&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; { &lt;span style=&#34;color:#a6e22e&#34;&gt;Foo&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;Bar&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Maybe this is what the &lt;code&gt;-s&lt;/code&gt; switch of &lt;code&gt;gofmt&lt;/code&gt; does (I haven&amp;rsquo;t checked). If so, I&amp;rsquo;m not sure why this switch is not set/available in &lt;code&gt;go fmt&lt;/code&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2026/07/03/turns-out-im-in-the.html</link>
      <pubDate>Fri, 03 Jul 2026 08:50:59 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2026/07/03/turns-out-im-in-the.html</guid>
      <description>&lt;p&gt;Turns out &lt;a href=&#34;https://intheweights.com/p/leon-mika&#34;&gt;I&amp;rsquo;m in the weights&lt;/a&gt;. They know I&amp;rsquo;m a software engineer, but not much more than that. Hilariously, Claude and Gemini think I&amp;rsquo;m a Swift developer and contributor. I guess the models have a problem recognising Go as a proper noun (or there&amp;rsquo;s a Leon Mika out there that&amp;rsquo;s a legendary Swift dev).&lt;/p&gt;
&lt;img src=&#34;https://cdn.uploads.micro.blog/25293/2026/in-the-weights.png&#34; width=&#34;580&#34; height=&#34;600&#34; alt=&#34;An export from intheweights.com for Leon Mika, who is identified as a Swift developer and blogger with a strength score of 220, placing him in the top 25%, alongside a comparison of various AI models&#39; performances.&#34;&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2026/06/26/ive-found-myself-using-ptal.html</link>
      <pubDate>Fri, 26 Jun 2026 12:36:40 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2026/06/26/ive-found-myself-using-ptal.html</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve found myself using PTAL at work, as a shorthand for &amp;ldquo;please take another look.&amp;rdquo; And it doesn&amp;rsquo;t seem to be a very common shorthand in the circles I work in: I&amp;rsquo;m usually asked what I mean. Is it a well-known shorthand in other circles? The US, maybe? I picked it up from the Go project.&lt;/p&gt;

  &lt;span class=&#34;clearfix-hack&#34;&gt;&lt;/span&gt;
  &lt;blockquote class=&#34;alert alert-selfreply&#34;&gt;
    &lt;p class=&#34;alert-heading&#34;&gt;
      
    &lt;/p&gt;
    &lt;p&gt;&lt;time datetime=&#34;2026-06-26T02:25:00Z&#34; class=&#34;reply-timestamp&#34;&gt;12:45&lt;/time&gt; I&amp;rsquo;ve never so badly wanted to add a poll to this site until today.&lt;/p&gt;
  &lt;/blockquote&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2026/06/19/i-do-wonder-if-the.html</link>
      <pubDate>Fri, 19 Jun 2026 06:46:20 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2026/06/19/i-do-wonder-if-the.html</guid>
      <description>&lt;p&gt;I do wonder if the broader Go community would adopt the new UUID package. It&amp;rsquo;s purely additive so it&amp;rsquo;s not like they need to, but the strength of any one library package depends on how many people use it. There&amp;rsquo;s a lot of network effects involved. I definitely will make use of it, but if database client don&amp;rsquo;t, it will be quite disappointing.&lt;/p&gt;
&lt;p&gt;I feel like they would though. There is some precedent of Go developers adopting new language features, such as threading &lt;code&gt;context.Context&lt;/code&gt; calls throughout the call graph. So my hopes are high.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2026/06/16/i-wish-gos-errgroup-returned.html</link>
      <pubDate>Tue, 16 Jun 2026 10:49:31 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2026/06/16/i-wish-gos-errgroup-returned.html</guid>
      <description>&lt;p&gt;I wish Go&amp;rsquo;s &lt;a href=&#34;https://pkg.go.dev/golang.org/x/sync/errgroup&#34;&gt;errgroup&lt;/a&gt; returned all the errors from the go-routines, not just the first one. It&amp;rsquo;s inherently leads to race conditions: I&amp;rsquo;ve lost useful error details because the error return is from the context being cancelled due to an error, not the error itself. Makes debugging difficult.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2026/06/10/still-wishing-for-enums-in.html</link>
      <pubDate>Wed, 10 Jun 2026 09:59:53 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2026/06/10/still-wishing-for-enums-in.html</guid>
      <description>&lt;p&gt;Still wishing for enums in Go. And now, after looking at a piece of code feating optional pointer types, I wished Go had unions too. In fact, Go should just bite the bullet and implement algebraic data types already, a.la. &lt;a href=&#34;https://www.schoolofhaskell.com/school/starting-with-haskell/introduction-to-haskell/2-algebraic-data-types&#34;&gt;Haskell&lt;/a&gt;. But would it still be Go if they did?&lt;/p&gt;

</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2026/06/04/amusing-to-find-myself-being.html</link>
      <pubDate>Thu, 04 Jun 2026 16:34:08 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2026/06/04/amusing-to-find-myself-being.html</guid>
      <description>&lt;p&gt;Amusing to find myself being roped into a release of… something, that needs to go out this week. Not entirely sure what needs to go out, and I don&amp;rsquo;t think anyone else does either. But damnit, it must be released by Friday!&lt;/p&gt;
&lt;img src=&#34;https://cdn.uploads.micro.blog/25293/2026/out-20260604-163312.png&#34; width=&#34;600&#34; height=&#34;809&#34; alt=&#34;Auto-generated description: A standing man in casual attire appears to speak to a group of seated individuals, evoking attention and interest, accompanied by the text Isn&#39;t knowing what you want a precondition of getting what you want?&#34;&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2026/06/03/found-this-gem-of-a.html</link>
      <pubDate>Wed, 03 Jun 2026 10:00:28 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2026/06/03/found-this-gem-of-a.html</guid>
      <description>&lt;p&gt;Found this &lt;a href=&#34;https://pkg.go.dev/time@go1.26.4#:~:text=It%20is%20a%20regrettable%20historic%20error%20that%20the%20date%20uses%20the%20American%20convention%20of%20putting%20the%20numerical%20month%20before%20the%20day.&#34;&gt;gem of a remark&lt;/a&gt; in the documentation of Go&amp;rsquo;s time formatting string:&lt;/p&gt;

  &lt;blockquote&gt;
    &lt;p&gt;It is a regrettable historic error that the date uses the American convention of putting the numerical month before the day.&lt;/p&gt;

  &lt;/blockquote&gt;
&lt;p&gt;Yeah, kind of wish we &lt;a href=&#34;https://man7.org/linux/man-pages/man1/date.1.html#:~:text=%25D%20%20%20%20%20date%20(ambiguous)%3B%20same%20as%20%25m/%25d/%25y&#34;&gt;learnt from history&lt;/a&gt; on this one. 😼&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2026/05/19/ttl-that-hc-the-go.html</link>
      <pubDate>Tue, 19 May 2026 15:30:53 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2026/05/19/ttl-that-hc-the-go.html</guid>
      <description>&lt;p&gt;TTL that &lt;a href=&#34;https://pkg.go.dev/golang.org/x/net/http2/h2c&#34;&gt;h2c&lt;/a&gt;, the Go HTTP handler that allows for unencrypted HTTP/2 connections, does not do graceful shutdowns. When you call &lt;code&gt;http.Shutdown()&lt;/code&gt; on a server using this hijacking handler, instead of draining the active request, it just kills the server. The good news is that it&amp;rsquo;s now deprecated in favour of &lt;a href=&#34;https://pkg.go.dev/net/http#Protocols&#34;&gt;http.Protocols&lt;/a&gt;, which doesn&amp;rsquo;t have this problem.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2026/05/09/blain-smith-just-fucking-use.html</link>
      <pubDate>Sat, 09 May 2026 08:32:39 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2026/05/09/blain-smith-just-fucking-use.html</guid>
      <description>&lt;p&gt;🔗 &lt;a href=&#34;https://blainsmith.com/articles/just-fucking-use-go/&#34;&gt;Blain Smith: Just Fucking Use Go&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There are not enough &amp;ldquo;this&amp;quot;es in the English language I can add in support for this post.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2026/05/04/might-be-time-to-take.html</link>
      <pubDate>Mon, 04 May 2026 12:22:12 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2026/05/04/might-be-time-to-take.html</guid>
      <description>&lt;p&gt;Might be time to take another look at Zed. Got &lt;a href=&#34;https://zed.dev/docs/languages/go&#34;&gt;Go properly setup&lt;/a&gt; in it and used it to fix a small bug. I have to do something about the font, but it feels pretty featureful compared to the last time I looked. Shows some decent promise.&lt;/p&gt;

</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2026/05/01/a-gentle-reminder-that-just.html</link>
      <pubDate>Fri, 01 May 2026 07:56:17 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2026/05/01/a-gentle-reminder-that-just.html</guid>
      <description>&lt;p&gt;A gentle reminder that just because you have a coding agent, doesn&amp;rsquo;t mean everything needs to go through the coding agent. If something can achieved using a traditional command invocation, just use that. It&amp;rsquo;ll burn zero tokens and would end up being faster in the long run.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Could Swift&#39;s Guard Statement Work in Go?</title>
      <link>https://lmika.org/2026/04/30/could-swifts-guard-statement-work.html</link>
      <pubDate>Thu, 30 Apr 2026 22:26:05 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2026/04/30/could-swifts-guard-statement-work.html</guid>
      <description>&lt;p&gt;While writing yet another &lt;code&gt;if&lt;/code&gt; block to check whether a map had a value, I asked myself a question: could Swift&amp;rsquo;s  &lt;code&gt;guard&lt;/code&gt; statement work in Go?&lt;/p&gt;
&lt;p&gt;Go is such an &lt;code&gt;if&lt;/code&gt; heavy language. You&amp;rsquo;re adding &lt;code&gt;if&lt;/code&gt; statements pretty much everywhere: after you receive an error, after you do a type assertion, when you want to verify that a map has a value. All of these come to you in the form of tuples, with the last one being the value to switch on:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;thing&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;doSomething&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Having a way to switch like this within an expression would be amazing. It could be an operator that would strip out the last value and pass it through to an &lt;code&gt;else&lt;/code&gt; block when it&amp;rsquo;s either non-nil (for errors) or false (for bools). Otherwise, it would simply return everything else:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;thing&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;guard&lt;/span&gt; { &lt;span style=&#34;color:#a6e22e&#34;&gt;doSomething&lt;/span&gt;() } &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; { &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I believe this is achievable in Swift using &lt;code&gt;guard&lt;/code&gt; or &lt;code&gt;guard let&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; thing = doSomething() &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; { &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But thinking about it for more than a few minutes, I can&amp;rsquo;t really see this workable in Go. It&amp;rsquo;s easy enough for Swift to have this, with it&amp;rsquo;s nullability baked into the type system. If a value is either something or nothing, then simply returning that something as the result of an expression is a natural thing to do.&lt;/p&gt;
&lt;p&gt;And because there&amp;rsquo;s only one variable, there&amp;rsquo;s no need to do things like declare that &lt;code&gt;err&lt;/code&gt; is the variable to receive the last parameter. That&amp;rsquo;s right, there&amp;rsquo;s no variable declaration of &lt;code&gt;err&lt;/code&gt; in that &lt;code&gt;else&lt;/code&gt; branch in that first example. Could you assume that the variable name would be &lt;code&gt;err&lt;/code&gt; if the last tuple value is of type &lt;code&gt;error&lt;/code&gt; (likewise, for &lt;code&gt;bool&lt;/code&gt; types, the implicit name would be &lt;code&gt;ok&lt;/code&gt;)? Well, you could, but it&amp;rsquo;d be pretty ugly. You&amp;rsquo;re now relying on knowledge not evident in the code, a property that goes against Go&amp;rsquo;s effort to be clear.&lt;/p&gt;
&lt;p&gt;Another problem is the use of blocks over function calls. In Go, the &lt;code&gt;defer&lt;/code&gt; and &lt;code&gt;go&lt;/code&gt; statements actually takes a function call. The semantics of a regular function call are the same, it&amp;rsquo;s just when the function is dispatched that differs. One could argue that in order to keep the design consistent, a &lt;code&gt;guard&lt;/code&gt; statement would need similar semantics: a function which returns at least two results. This is probably not a deal breaker, but it would be a little limiting, and would break the ability to nest these in a single expression without making lambdas.&lt;/p&gt;
&lt;p&gt;The closest plausible solution I could come up with is a new statement that uses this property, and combines it with an assignment and &lt;code&gt;else&lt;/code&gt; block. Something along the lines of:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;thing&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;doSomething&lt;/span&gt;() &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; { &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;While this looks like it includes a regular assignment, its presence will actually be baked into the syntax, and would be used to declare the variables that would accept the function result. Once called, and the tuple returned, the statement will assign it to the declared variables, and branch to &lt;code&gt;else&lt;/code&gt; based on the last value&amp;rsquo;s type. If it&amp;rsquo;s &lt;code&gt;error&lt;/code&gt;, it will branch when it&amp;rsquo;s non-nil; if it&amp;rsquo;s &lt;code&gt;bool&lt;/code&gt;, it&amp;rsquo;ll branch when it&amp;rsquo;s false (anything else will be a type error). If the branch isn&amp;rsquo;t taken, the other variables will be available to anything beyond it (this is one of the key differences with the existing assignment based &lt;code&gt;if&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Because the assignment is required to declare the necessary variables, this has to be a statement, and cannot be nested. Such limitation feels critical to the usefulness of this, and if proposed, its worth in the language would probably be questioned. That&amp;rsquo;s a lot of new syntax for something that&amp;rsquo;s marginally better than an &lt;code&gt;if&lt;/code&gt; block.&lt;/p&gt;
&lt;p&gt;So I&amp;rsquo;m doubtful something like this will see its presence in Go anytime soon. But it&amp;rsquo;s been an interesting exercise.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Devlog: Imagen</title>
      <link>https://lmika.org/2026/04/26/devlog-imagen.html</link>
      <pubDate>Sun, 26 Apr 2026 11:18:46 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2026/04/26/devlog-imagen.html</guid>
      <description>&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; I&amp;rsquo;ve recently been aware that Google actually has an image model call Imagen. This post has nothing to do with this. I was unaware of this model when I started working on this project. The naming was purely coincidental.&lt;/p&gt;
&lt;p&gt;I won&amp;rsquo;t bore you with any justification on why I actually built this thing. It&amp;rsquo;s really nothing more than wanting a harness to play with Google&amp;rsquo;s Nano Banana. Up until now, I&amp;rsquo;ve been using Blogging Tools for that, but it lacked any ability to request changes to images in a chat-like interface (so called &amp;ldquo;multi-step flows&amp;rdquo;), where the context is preserved. So I made Imagen as a replacement.&lt;/p&gt;
&lt;div class=&#34;img-gallery&#34;&gt;
&lt;figure&gt;
&lt;img src=&#34;https://lmika.org/uploads/2026/cleanshot-2026-04-26-at-11.00.58.png&#34;
     
      /&gt;

  &lt;figcaption&gt;
  
  The landing page, showing current chat sessions and &amp;#39;assets&amp;#39; (uploaded and generated images).
  &lt;/figcaption&gt;

&lt;/figure&gt;
&lt;figure&gt;
&lt;img src=&#34;https://lmika.org/uploads/2026/cleanshot-2026-04-26-at-11.01.22.png&#34;
     
      /&gt;

  &lt;figcaption&gt;
  
  An example of a chat session, showing the meta-commands, plus messages from the user and model.
  &lt;/figcaption&gt;

&lt;/figure&gt;
&lt;figure&gt;
&lt;img src=&#34;https://lmika.org/uploads/2026/cleanshot-2026-04-26-at-11.01.29.png&#34;
     
      /&gt;

  &lt;figcaption&gt;
  
  Clicking &amp;#39;New Chat&amp;#39; will show you this: a prompt window along with a way to upload images.
  &lt;/figcaption&gt;

&lt;/figure&gt;
&lt;figure&gt;
&lt;img src=&#34;https://lmika.org/uploads/2026/cleanshot-2026-04-26-at-11.01.40.png&#34;
     
      /&gt;

  &lt;figcaption&gt;
  
  Chat management section, allowing you to archive or delete any chats.
  &lt;/figcaption&gt;

&lt;/figure&gt;
&lt;figure&gt;
&lt;img src=&#34;https://lmika.org/uploads/2026/cleanshot-2026-04-26-at-11.01.49.png&#34;
     
      /&gt;

  &lt;figcaption&gt;
  
  Clicking the gear icon brings you to the admin section, allowing you to revoke passkeys and end your session.
  &lt;/figcaption&gt;

&lt;/figure&gt;
&lt;/div&gt;
&lt;p&gt;This is a pretty typical chat-based AI model harness. You start a chat requesting an image, maybe uploading one you want modified, click &amp;ldquo;Send&amp;rdquo;, and wait for the model to respond.  There also exist a bunch of meta commands, entered using the &lt;code&gt;/&lt;/code&gt; prefix, that allow you change the model, and retry or undo the last request.&lt;/p&gt;
&lt;p&gt;Chats and assets are stored as regular files (assets as regular image files, chats as a Gob-serialised history of the chat) and metadata is managed by a Sqlite3 database. In terms of the tech stack, I&amp;rsquo;ve settled on a mix that works well for me. A Go backend, using &lt;a href=&#34;https://gofiber.io&#34;&gt;Fiber&lt;/a&gt; as the web middleware, and Go templates for server-side rendering. I eschewed Stimulus.js for this one though, deciding to try out &lt;a href=&#34;https://htmx.org&#34;&gt;HTMX&lt;/a&gt;. And it&amp;rsquo;s a unique way of working. I learnt that to really get the most out of HTMX, you really need to find ways not to use JavaScript to do something.&lt;/p&gt;
&lt;p&gt;The chat interface is a good example. While a more traditional frontend would post a message as JSON and rerender the page with a JSON response, posting a chat message here would return a server-side HTML render of the chat interface, which HTMX will swap out. This also include things like the message form itself, which would be rendered disabled from the server template, rather than being controlled by JavaScript. The good thing about that is that if you were to hard-refresh the page, it will appear disabled. No need to run JavaScript on load to detect the state and disable the form: the HTML is the state. As for getting updates while waiting for a message, well that&amp;rsquo;s just a poll. Nothing too sophisicated here.&lt;/p&gt;
&lt;p&gt;As you can probably guess, much of this was hand-rolled. I did use coding agents to assist with making the passkey authentication flow, the meta commands, and the OpenAI API integration. While I probably could&amp;rsquo;ve done the last two myself, if there was any justification for using coding agents for anything it was probably adding passkeys. The complexity involved with the passkey integration probably justified the use . And this is probably one area of AI-generated code that I&amp;rsquo;m more likely to trust the model over my own shoddy code.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2026/04/07/sky-an-elminspired-language-that.html</link>
      <pubDate>Tue, 07 Apr 2026 07:57:13 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2026/04/07/sky-an-elminspired-language-that.html</guid>
      <description>&lt;p&gt;🛠️ &lt;a href=&#34;https://github.com/anzellai/sky&#34;&gt;Sky — an Elm-inspired language that compiles to Go&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Kind of striking seeing Go becoming the target of other languages. Here&amp;rsquo;s another one. Looks a bit like Haskell to my eyes.&lt;/p&gt;
&lt;p&gt;Via: &lt;a href=&#34;https://news.ycombinator.com/item?id=47662116&#34;&gt;Hacker News&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2026/04/05/lisette-rust-syntax-go-a.html</link>
      <pubDate>Sun, 05 Apr 2026 07:46:22 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2026/04/05/lisette-rust-syntax-go-a.html</guid>
      <description>&lt;p&gt;🛠️ &lt;a href=&#34;https://lisette.run/&#34;&gt;Lisette — Rust syntax, Go runtime&lt;/a&gt;&lt;/p&gt;

  &lt;blockquote&gt;
    &lt;p&gt;A little language inspired by Rust that compiles to Go&lt;/p&gt;

  &lt;/blockquote&gt;
&lt;p&gt;This looks really interesting.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2026/03/14/it-looks-like-gos-getting.html</link>
      <pubDate>Sat, 14 Mar 2026 17:33:47 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2026/03/14/it-looks-like-gos-getting.html</guid>
      <description>&lt;p&gt;It looks like &lt;a href=&#34;https://github.com/golang/go/issues/62026#issuecomment-4041188661&#34;&gt;Go&amp;rsquo;s getting a UUID package&lt;/a&gt; added to the standard library. Someone&amp;rsquo;s been reading my mind, or at the very least &lt;a href=&#34;https://lmika.org/2023/05/19/i-think-its.html&#34;&gt;reading my&lt;/a&gt; &lt;a href=&#34;https://lmika.org/2025/10/15/argh-why-hasnt-go-got.html&#34;&gt;blog&lt;/a&gt;. 😏&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2026/03/07/my-coolify-instance-has-been.html</link>
      <pubDate>Sat, 07 Mar 2026 07:23:59 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2026/03/07/my-coolify-instance-has-been.html</guid>
      <description>&lt;p&gt;My Coolify instance has been running really slowly over the last few days. I may start looking at alternatives, or maybe go back to using Dokku.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2026/03/05/go-iterators-dont-have-a.html</link>
      <pubDate>Thu, 05 Mar 2026 21:20:18 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2026/03/05/go-iterators-dont-have-a.html</guid>
      <description>&lt;p&gt;Go iterators don&amp;rsquo;t have a built in way to send errors back, so I borrowed something from Haskell and made a &amp;ldquo;maybe&amp;rdquo; type:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Maybe&lt;/span&gt;[&lt;span style=&#34;color:#a6e22e&#34;&gt;T&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;any&lt;/span&gt;] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;Value&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;T&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;Err&lt;/span&gt;   &lt;span style=&#34;color:#66d9ef&#34;&gt;error&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;m&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Maybe&lt;/span&gt;[&lt;span style=&#34;color:#a6e22e&#34;&gt;T&lt;/span&gt;]) &lt;span style=&#34;color:#a6e22e&#34;&gt;Get&lt;/span&gt;() (&lt;span style=&#34;color:#a6e22e&#34;&gt;T&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;error&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;m&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Value&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;m&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Err&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The iterator pushes values wrapped in this, which would have &lt;code&gt;Value&lt;/code&gt; set if one is available, or &lt;code&gt;Err&lt;/code&gt; set if not. The &lt;code&gt;Get()&lt;/code&gt; method provides a convenient way to get both, allowing for patterns that look much like the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;consume&lt;/span&gt;() &lt;span style=&#34;color:#66d9ef&#34;&gt;error&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;m&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;range&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;myIter&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;val&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;m&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Get&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;doThingWithVal&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;val&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2026/03/05/had-a-go-heh-at.html</link>
      <pubDate>Thu, 05 Mar 2026 21:13:34 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2026/03/05/had-a-go-heh-at.html</guid>
      <description>&lt;p&gt;Had a go (heh) at making a Go iterator. It was simpler than I expected, once I got my head around how they work. It&amp;rsquo;s a push model, the iterator pushes value to a yield function, which sends it to &lt;code&gt;range&lt;/code&gt;, and receives a flag on whether to continue. The &lt;a href=&#34;https://pkg.go.dev/iter&#34;&gt;package docs&lt;/a&gt; do a good job explaining this.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2026/02/27/a-bit-frustrating-that-i.html</link>
      <pubDate>Fri, 27 Feb 2026 09:24:29 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2026/02/27/a-bit-frustrating-that-i.html</guid>
      <description>&lt;p&gt;A bit frustrating that I asked my IDE to rename all instances of a method, and it did around half of them, ignoring the interfaces the type implements. I know Go interfaces are different to Java interfaces, but if the type checker passes already, rename things such that it remains that way.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2026/01/27/reason-go-should-add-enums.html</link>
      <pubDate>Tue, 27 Jan 2026 09:31:01 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2026/01/27/reason-go-should-add-enums.html</guid>
      <description>&lt;p&gt;Reason Go should add enums number 5,132: you&amp;rsquo;re not left up to runtime checks to verify that an enum value is invalid. You can rely on the type system to do that. It&amp;rsquo;s all well and good to implement marshallers and unmarshallers that verify that the input is a valid enum value, but that doesn&amp;rsquo;t stop developers from casting any arbitrary string to your enum type. And then what are you expected to do in your String() method (which doesn&amp;rsquo;t return an error)? Do you panic? Return &amp;ldquo;invalid?&amp;rdquo; Return the string enum value as is, even if it is invalid?&lt;/p&gt;
&lt;p&gt;Making it impossible to even produce invalid types is the whole reason why we have a type system. It&amp;rsquo;s why I prefer Go over an untyped language like Python and JavaScript. So it would be nice if Go supported enums in the type system to get this guarantee.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2026/01/24/added-my-to-the-other.html</link>
      <pubDate>Sat, 24 Jan 2026 06:43:25 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2026/01/24/added-my-to-the-other.html</guid>
      <description>&lt;p&gt;Added my 👍 to the other 192 on this &lt;a href=&#34;https://github.com/golang/go/issues/77273&#34;&gt;Go proposal to add generics to methods&lt;/a&gt;. Great idea! I&amp;rsquo;ve been wishing for this for a while.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2026/01/14/its-so-satisfying-seeing-the.html</link>
      <pubDate>Wed, 14 Jan 2026 06:46:00 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2026/01/14/its-so-satisfying-seeing-the.html</guid>
      <description>&lt;p&gt;It&amp;rsquo;s so satisfying seeing the run of a large Go test suite reveal itself as a tree when executed in an editor. IDEs should lean into this, allowing execution of subtests to any depth (not just the top + 1 level), and offering features like find.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Devlog: An API For a Keyframe Animation Package</title>
      <link>https://lmika.org/2025/12/30/devlog-an-api-for-a.html</link>
      <pubDate>Tue, 30 Dec 2025 16:42:35 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2025/12/30/devlog-an-api-for-a.html</guid>
      <description>&lt;p&gt;Spent the day building a key-frame animator for an Ebitengine project. All coded in Go, which should make it usable for some other projects in theory. I don&amp;rsquo;t have a lot of experience with animation frameworks — other than as an end-user of apps that consist of a timeline where I place keyframes — so I&amp;rsquo;m not aware of what constitutes best practice for a programatic API. So I set out to build one with an API that made sense to me. After one major iteration, this is the approach I came up with.&lt;/p&gt;
&lt;p&gt;The core model type is the Var, which represents an animatable value. These are essentially handles describing the type of value the (package) user wants to animate. At the moment there is only a single type, which is a float:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;xPos&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;animator&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;NewFloatVar&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;yPos&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;animator&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;NewFloatVar&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To animate the value, the user will need to create an Animation and place any created Vars on a track. Tracks consist of key-frames, which is essentially a time offset, and one or more values a Var should have at that time. These values can be created from the Var itself, by calling &lt;code&gt;Set()&lt;/code&gt;.   This returns a type holding what that Var should be set to at that key-frame (&amp;ldquo;set&amp;rdquo; is probably not the best term for this):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;moveDown&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;animator&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;NewAnimation&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;posTrack&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;moveDown&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;NewTrack&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;posTrack&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;KeyFrame&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;0.0&lt;/span&gt;, []&lt;span style=&#34;color:#a6e22e&#34;&gt;animator&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;FloatSet&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;xPos&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Set&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;0.0&lt;/span&gt;), &lt;span style=&#34;color:#a6e22e&#34;&gt;yPos&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Set&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;0.0&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;posTrack&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;KeyFrame&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;3.0&lt;/span&gt;, []&lt;span style=&#34;color:#a6e22e&#34;&gt;animator&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;FloatSet&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;xPos&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Set&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;100.0&lt;/span&gt;), &lt;span style=&#34;color:#a6e22e&#34;&gt;yPos&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Set&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;100.0&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Not all Vars need to be included on a particular keyframe, but prior to animating, each of the Vars known to the track will need to be tweened if there isn&amp;rsquo;t a &amp;ldquo;set&amp;rdquo; for them on the key-frame, so it&amp;rsquo;s generally good practice to set all the Vars for each track. Different tracks can have a different of Vars, so if different keyframes are needed, it probably should exist on a separate track.&lt;/p&gt;
&lt;p&gt;Animations are designed to be reusable and simply encode what the Animation is. The motivation here is that all the expensive work should be done once, when the Animation is created. To actually animate the Vars, the user will need to create a timeline and set it to the Animation.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;tl&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;animator&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;NewTimeline&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;tl&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;SetAnimation&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;moveDown&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will initialise all the Var values to what they would be at frame 0 (at the moment, frame 0 must be a time 0, but down the line I&amp;rsquo;d like to remove this to allow for blending between Animations). The value of each Var can now be retrieved, as Vars only have a value within the scope of a Timeline.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;xPos&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Value&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;tl&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;yPos&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Value&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;tl&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// x and y == 0, as that is the value they were set to in the first frame&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;drawRect&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;x&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;y&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The Timeline clock is advanced by calling the &lt;code&gt;Advance()&lt;/code&gt; method, which takes a delta in fractions of a second. This will tween all the Vars based on the current action, and the new value can be retrieved by calling &lt;code&gt;Value()&lt;/code&gt; again. Thus the core use of this package is advancing the clock and querying the values for each tweened frame.&lt;/p&gt;
&lt;p&gt;Within an Ebitengine project, this is done by calling &lt;code&gt;Advance&lt;/code&gt; within &lt;code&gt;Update&lt;/code&gt; function and sampling the values within &lt;code&gt;Draw&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;tl&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;animator&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Timeline&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;xPos&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;animator&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;FloatVar&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;yPos&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;animator&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;FloatVar&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Update&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;dt&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1.0&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt; float64(&lt;span style=&#34;color:#a6e22e&#34;&gt;ebiten&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;TPS&lt;/span&gt;())  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;tl&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Advance&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;dt&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Draw&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;screen&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;ebiten&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Image&lt;/span&gt;) {  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;vector&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;FillRect&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;screen&lt;/span&gt;,  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       float32(&lt;span style=&#34;color:#a6e22e&#34;&gt;xPos&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Value&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;tl&lt;/span&gt;)), float32(&lt;span style=&#34;color:#a6e22e&#34;&gt;yPos&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Value&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;tl&lt;/span&gt;)),  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;,  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#a6e22e&#34;&gt;col&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;,  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here&amp;rsquo;s an test animation:&lt;/p&gt;
&lt;p&gt;&lt;video src=&#34;https://cdn.uploads.micro.mov/25293/2025/cleanshot-2025-12-30-at-17.14.42/playlist.m3u8&#34; poster=&#34;https://cdn.uploads.micro.blog/25293/2025/frames/1647920-0-36a228.jpg&#34; width=&#34;1232&#34; height=&#34;720&#34; controls=&#34;controls&#34; preload=&#34;metadata&#34;&gt;&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m quite happy with how this turns out. I like how little &amp;ldquo;magic&amp;rdquo; is involved in the API: values and clocks are not changed from underneath you: you need to explicitly advance the clock yourself, and read the values when you need them.&lt;/p&gt;
&lt;p&gt;Obviously there&amp;rsquo;s room for improvement. Tracks and keyframes cannot be changed; only linear interpolation of float values are supported; and there&amp;rsquo;s no looping, bouncing, or reversing of animations. I&amp;rsquo;d hope to add all this in due time, probably based on the needs of the project I&amp;rsquo;m working on. There are also a few things I&amp;rsquo;m a little wary of, such as a global atomic int responsible for allocating an ID for each newly created Var. And the Timeline holds Var values in a map which I hope is fast enough for rendering on a screen.&lt;/p&gt;
&lt;p&gt;But it&amp;rsquo;s nice to have something like this in my toolbox. It&amp;rsquo;s been something I&amp;rsquo;ve been wishing for a while.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2025/12/28/achievement-unlocked-setting-up-a.html</link>
      <pubDate>Sun, 28 Dec 2025 10:11:51 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2025/12/28/achievement-unlocked-setting-up-a.html</guid>
      <description>&lt;p&gt;Achievement unlocked: setting up a CI/CD pipeline the builds a Go WASM project and deploys it to Netlify that worked first try.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Devlog: Blogging Tools - Image Collections Triage App</title>
      <link>https://lmika.org/2025/11/29/devlog-blogging-tools-image-collections.html</link>
      <pubDate>Sat, 29 Nov 2025 09:54:02 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2025/11/29/devlog-blogging-tools-image-collections.html</guid>
      <description>&lt;p&gt;Up until now, I&amp;rsquo;ve been using Blogging Tools&amp;rsquo; in-app notification system to sort images to collections. There were quite a few limitations in doing so: only notifications for the first for images were raised, galleries weren&amp;rsquo;t handled, and you could only select one category per image. I also wanted a way to automatically change the header image in this blog. This was done using the image category notification, but it was pretty basic in that the image was chosen as the header if any category was selected.&lt;/p&gt;
&lt;p&gt;I had ideas of improving all of this but I realised quickly that I needed something more sophisticated to do so. So I added another app to Blogging Tools to do this. I also thought to try out using Antigravity to do this. I was curious to know how well Google Gemini would work with a project that already had an established architecture and coding patterns. I was also curious to know how Antigravity felt when I held a tighter grip of the reigns: I wanted to drive the development work and only turning to the agent when I need something done.&lt;/p&gt;
&lt;p&gt;I started simply enough: I built a basic HTML template for this new app and asked Gemini to prepare a stub handler:&lt;/p&gt;

  &lt;blockquote&gt;
    &lt;p&gt;Please create a new handler that services the template &amp;ldquo;imageposts/show.html&amp;rdquo;. Implement it much like the other handlers found in the &amp;ldquo;handlers&amp;rdquo; directory.&lt;/p&gt;

  &lt;/blockquote&gt;
&lt;p&gt;I forgot to mention to the agent that this was to be a stub, and it ended up using the existing provider for the gallery app. But it was pretty close to what I wanted. I then asked it to suggest a good HTML entity for opening a page in an external window.&lt;/p&gt;

  &lt;blockquote&gt;
    &lt;p&gt;What&amp;rsquo;s a good HTML entity for indicating that a link will open up into an external window/tab?&lt;/p&gt;

  &lt;/blockquote&gt;
&lt;p&gt;It suggested &lt;code&gt;↗&lt;/code&gt;, also a good answer. I then went on to build the Go models and wanted to work on the CSS styling next, so I asked Gemini to produce some example data using these models:&lt;/p&gt;

  &lt;blockquote&gt;
    &lt;p&gt;Please generate 3 stubbed values for this item slice. Use real example image URLs for the source.&lt;/p&gt;

  &lt;/blockquote&gt;
&lt;p&gt;It struggled a little on this one, suggesting a URL that didn&amp;rsquo;t exist. But after pointing this out, it got there in the end. It was at this point that I needed to do some refactoring to some of the existing services, needing to extract out a type that used only the values from another type. Gemini did quite well here too:&lt;/p&gt;

  &lt;blockquote&gt;
    &lt;p&gt;Note the select call. At the moment this is returning a micropub.Item model. I want to make a new model called &amp;ldquo;ImageCollection&amp;rdquo; that uses only the values of this micropub.Item that the code is currently using now. I don&amp;rsquo;t want the micropub.Item changed, but any code that is using this for the purpose of the selected call should include a map to this new model.&lt;/p&gt;

  &lt;/blockquote&gt;
&lt;p&gt;I guess this is not a novel experience to anyone using Cursor, but what I really liked about this interaction is that I was free to work on other things or move away from the keyboard entirely while the agent was working. This is one annoyance that I have with Claude Code: the exchange pauses and waits for me to approve every change before it proceeds. Having Gemini plan the changes first, then have me approve them once I&amp;rsquo;m back is a much nicer way of working.&lt;/p&gt;
&lt;p&gt;I then turned to the database schema, defining the table schema and SQL queries myself, and asking Gemini to produce the Go code that marshals the data: the so called &amp;ldquo;database providers&amp;rdquo;.&lt;/p&gt;

  &lt;blockquote&gt;
    &lt;p&gt;Implement the Go DB provider for DB tables for the queries in &amp;ldquo;imageposts.sql&amp;rdquo;. Do it in a similar style to the other providers found in &amp;ldquo;providers/db&amp;rdquo;.&lt;/p&gt;

  &lt;/blockquote&gt;
&lt;p&gt;This is where I get the most use out of using coding agents. This code is not hard, but it&amp;rsquo;s super annoying to write. I think it also helps that there&amp;rsquo;s an established code base for the agent to work on. I was a little unhappy with what the agent produced last week, probably because it was required to produce it from scratch and in a way that wasn&amp;rsquo;t how I would write it. But here, probably because the agent had existing patterns to work on, it&amp;rsquo;s producing something that looks a lot better, to my eyes at least.&lt;/p&gt;
&lt;p&gt;It did struggle with the providers a little, choosing to merge an update to two models in a single method. I did try to correct it, but I just had to go in and fix it manually.&lt;/p&gt;

  &lt;blockquote&gt;
    &lt;p&gt;We can probably separate SaveImagePost into one that saves the ImagePost, and another that saves ImagePostItems.&lt;/p&gt;

  &lt;/blockquote&gt;
&lt;p&gt;One other thing I discovered is that getting Gemini to write unit tests is important, as it provides a way for the agent to verify it&amp;rsquo;s code. I approved a change Gemini produced without looking too closely, and if I were to test it myself, it would&amp;rsquo;ve failed. But only after I asked it to produce a unit test did I see it fix the errors introduced in the last interaction. Something to think about in the future.&lt;/p&gt;

  &lt;blockquote&gt;
    &lt;p&gt;Might be a good idea to implement a unit test to verify that the DB methods in imageposts.go work. Do this by creating a new db.Provider instance with a temporary file, and verifying that the provider methods of imageposts.go work as expected. Please use testify.Assert to do the asserts.&lt;/p&gt;

  &lt;/blockquote&gt;
&lt;p&gt;It was now time to build the service layer. This is something I wanted to drive myself, occasionally relying on auto-suggestions. Antigravity fell down (ha ha) here a little, producing suggestions that were pretty far from what I wanted. I guess it was lacking the context to know what I actually wanted, which is somewhat understandable as I wasn&amp;rsquo;t giving that context. It also seems to fight with IntelliSence from VS Code sometimes. I occasionally press tab in response to a type suggestion from the index, only to have it produce a completion for some unknown type. I do wish the suggestions use the code index more in general. There&amp;rsquo;ve been more than a few times where the agent suggested types and methods that just didn&amp;rsquo;t exist. Might be something that can be tuned.&lt;/p&gt;
&lt;p&gt;One quality of life improvement I did make was increase the timeout for when suggestions would appear. The default was something like 50 milliseconds, which is pretty short. Bumping it to 1 second helps, but even so they still get in the way. I may bump it a little higher.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&#34;https://cdn.uploads.micro.blog/25293/2025/pasted-image-20251129100529.png&#34; width=&#34;600&#34; height=&#34;449&#34; alt=&#34;Auto-generated description: A web interface for blogging tools features options to categorize or set an image of a scenic landscape as a header.&#34;&gt;
&lt;figcaption&gt;First cut of the collection triage screen at the end of day one.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;I worked on this feature over the next couple of evenings, occasionally changing tack which required a change in the database schema. One thing I did like while working on this was getting to the point where I could simply ask the agent to update the provider code whenever I did so, and it knew what I meant:&lt;/p&gt;

  &lt;blockquote&gt;
    &lt;p&gt;The ImagePost model and table schema now has a PostDate field/column. Please update the providers.&lt;/p&gt;

  &lt;/blockquote&gt;
&lt;p&gt;I do get the feeling that the user interaction in Antigravity needs to be refined a little. For someone who is willing to do most of the driving, it would be nice if the editor was a little less &amp;ldquo;needy&amp;rdquo;. This is probably more to do with VS Code being the underlying editor: lots of annoying popups and mouse overs, all shouting for my attention: LOOK AT THIS, LOOK AT THIS. But the AI suggestions don&amp;rsquo;t help. Instead of displaying the generated code, disrupting my sense of where everything is, maybe a more subtler approach is warranted: a small indicator beside the cursor or in the margin indicating that a suggestion is present. I may miss it, but who cares? Remember, I&amp;rsquo;m the one driving here.&lt;/p&gt;
&lt;p&gt;Today, I got the feature finished. The way it works is that it will poll the RSS feed of this blog, and for every post that has an image, it will add an entry for me to triage. Each entry consists of a brief summary, plus the images found within the post:&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&#34;https://cdn.uploads.micro.blog/25293/2025/pasted-image-20251129100017.png&#34; width=&#34;600&#34; height=&#34;449&#34; alt=&#34;Auto-generated description: A menu interface displaying various blogging tools and options for managing images, videos, and text.&#34;&gt;
&lt;figcaption&gt;A new &#39;Sort Image Posts&#39; app, with a badge indicating the number of images to triage.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;img src=&#34;https://cdn.uploads.micro.blog/25293/2025/pasted-image-20251129100346.png&#34; width=&#34;600&#34; height=&#34;449&#34; alt=&#34;Auto-generated description: Blogging interface featuring a post titled Under the big, grey sky-rail with a small image and options to edit or delete.&#34;&gt;
&lt;figcaption&gt;List of posts with images that need triaging.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Clicking through to the post would list the collections, and I would select the ones I&amp;rsquo;d like the image to be filed in. And this would list all the images of the post, not just the first few. It is all or nothing, unfortunately. There are ways to get the images of the collection, but I couldn&amp;rsquo;t see a way for me to get the collections of an image. I don&amp;rsquo;t think this would be a problem, as Blogging Tools is the only way I actually set the collections of an image.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&#34;https://cdn.uploads.micro.blog/25293/2025/pasted-image-20251129100432.png&#34; width=&#34;600&#34; height=&#34;449&#34; alt=&#34;Auto-generated description: A screen displays a blogging tool interface with an image of an elevated roadway and options for categorizing an image post.&#34;&gt;
&lt;figcaption&gt;Selecting a post will list the images found within that post, with the collections they should be added to.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Saving the categories will queue the changes, which will be applied every 5 minutes. A first cut of this feature applied the changes immediately, but the way I imagine using this is that I&amp;rsquo;d go in, triage the images in one go, then leave. Applying all the changes then felt inefficient.&lt;/p&gt;
&lt;p&gt;When it comes to setting the header image, I figured I&amp;rsquo;d add a dedicated collection for that. Every hour a cronjob will query the local database for images that is within this category, and write the URLs to a manifest file in the assets Git repository. A Forgejo Action on that repository runs every night, and will check the date-stamps for the next image to display on the header. If one is found, it will fetch the image, save it as a JPEG with reduced quality and upload to Netlify. Since Netlify flushes the CDN whenever a deployment happens, nothing more needs to be done: no MD5 sum hashes, no adjustment to CSS files. Just update &lt;code&gt;header.jpg&lt;/code&gt; and go:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Example of the manifest file.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;images&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;date&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2025-11-22T13:00:00Z&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://lmika.org/uploads/2025/pxl-20251120-083552448.jpg&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;crop&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;bottom&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;date&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2025-11-26T13:00:00Z&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://lmika.org/uploads/2025/a3c74bfebd.jpg&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Deployed all these changes to prod and naturally some rework that&amp;rsquo;s needed. First, I completely forgot about galleries. They do come through as image tags in the generated HTML, but I&amp;rsquo;m operating on the source post, and they appear as Hugo short-codes. Fortunately the way I write galleries is pretty standardised now, so I think a regular expression would work here.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;galleryRegexp&lt;/span&gt; = &lt;span style=&#34;color:#a6e22e&#34;&gt;regexp&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;MustCompile&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;`[{]{2}[&amp;lt;][ ]?glightbox.*src=&amp;#34;([^&amp;#34;]+)&amp;#34;.*[&amp;gt;][}]{2}`&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Oh, I also want to fix the layout of the collection checkboxes and hide some options, such as those that for past years. And finally, will turn off the existing image category notification logic.&lt;/p&gt;
&lt;p&gt;Deployed again, and now I just need to wait for the next time I post a photo. I suspect some bug fixes or usability adjustments will come from this, but more on that when that happens.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2025/11/06/kind-of-crazy-seeing-go.html</link>
      <pubDate>Thu, 06 Nov 2025 06:38:40 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2025/11/06/kind-of-crazy-seeing-go.html</guid>
      <description>&lt;p&gt;Kind of crazy seeing Go packages which are effectively WASM builds of C libraries running in a Go WASM runtime, like this &lt;a href=&#34;https://github.com/ncruces/go-sqlite3&#34;&gt;sqlite3&lt;/a&gt; port. So that&amp;rsquo;s WASM sandwiched between two layers of Go. A &amp;ldquo;WASM smash burger,&amp;rdquo; if you will. Still, if you want to avoid using Cgo, then I can understand the motivation.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2025/10/02/interesting-development-in-the-world.html</link>
      <pubDate>Thu, 02 Oct 2025 07:43:55 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2025/10/02/interesting-development-in-the-world.html</guid>
      <description>&lt;p&gt;Interesting development in the world of Go: in 1.26, the &lt;a href=&#34;https://utcc.utoronto.ca/~cks/space/blog/programming/GoNewWithExpression&#34;&gt;new() function will now accept expressions&lt;/a&gt;, not just types. This returns a pointer to the value, which will be useful for those types that use pointers for their fields:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;User&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#a6e22e&#34;&gt;Age&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;user&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;User&lt;/span&gt;{}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;age&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; = &lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;user&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Age&lt;/span&gt; = new(&lt;span style=&#34;color:#a6e22e&#34;&gt;age&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It also works for literal values, so that temporary &lt;code&gt;age&lt;/code&gt; variable is strictly not necessary, although the linked post does state that it requires some consideration for types. Having &lt;code&gt;user.Age = new(10)&lt;/code&gt; will work without issue as &lt;code&gt;new&lt;/code&gt; will return a &lt;code&gt;*int&lt;/code&gt;; but if &lt;code&gt;Age&lt;/code&gt; were a &lt;code&gt;*uint&lt;/code&gt;, you&amp;rsquo;ll get a type error.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://lmika.org/2024/11/12/ill-never-understand.html&#34;&gt;I go on&lt;/a&gt; about &lt;a href=&#34;https://lmika.org/2025/08/15/dear-go-developers-you-dont.html&#34;&gt;unnecessary pointer types&lt;/a&gt; in the past (and will probably continue to do so in the future). To me, it&amp;rsquo;s just one of those paper-cuts you encounter in your day to day that you know can be made easier. So I consider this a welcome change. It&amp;rsquo;s not going to same me a ton on code, but every little bit helps.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Learning To Like Sentinel Errors In Go</title>
      <link>https://lmika.org/2025/09/18/learning-to-like-sentinel-errors.html</link>
      <pubDate>Thu, 18 Sep 2025 09:24:50 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2025/09/18/learning-to-like-sentinel-errors.html</guid>
      <description>&lt;p&gt;I use to be someone who returned a nil value along with a nil error whenever I needed to indicate that a value was missing, like a database record. But recently, I&amp;rsquo;ve come around to the idea of returning either a result, or an error: never returning neither.&lt;/p&gt;
&lt;p&gt;It may not be technically correct. If something doesn&amp;rsquo;t exist in a database, one can make the argument that a function implemented in a way that, when said aloud, would effectively be &amp;ldquo;well, I didn&amp;rsquo;t have any errors trying to find the thing; but I couldn&amp;rsquo;t find the thing either, so I got nothing successfully.&amp;rdquo; And I know that sentinel errors is &lt;a href=&#34;https://dave.cheney.net/2016/04/27/dont-just-check-errors-handle-them-gracefully#:~:text=So%2C%20my%20advice%20is%20to%20avoid%20using%20sentinel%20error%20values%20in%20the%20code%20you%20write.%20There%20are%20a%20few%20cases%20where%20they%20are%20used%20in%20the%20standard%20library%2C%20but%20this%20is%20not%20a%20pattern%20that%20you%20should%20emulate.&#34;&gt;generally frowned upon by certain Go language designers&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;But I think it makes for more readable code; dare I say, more empathetic code. If much of what you write in Go is stuff like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;res&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;getThingFromDB&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then I think it&amp;rsquo;s safe to assume that the reader will think that &lt;code&gt;res&lt;/code&gt; will have a value if &lt;code&gt;err&lt;/code&gt; is nil. I know it&amp;rsquo;s generally not correct to assume that, just like it&amp;rsquo;s not correct to assume that a pointer value is never nil. But us coders are still human (at least for now), and doing the obvious thing is still better than being technically correct.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Devlog: Dequoter — Something Different Today</title>
      <link>https://lmika.org/2025/09/06/devlog-dequoter-something-different-today.html</link>
      <pubDate>Sat, 06 Sep 2025 16:10:04 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2025/09/06/devlog-dequoter-something-different-today.html</guid>
      <description>&lt;p&gt;When it comes to hobby projects, I&amp;rsquo;m trying to reduce the number of things I build for work. But I&amp;rsquo;ve decided to revisit one that I&amp;rsquo;ve abandoned, given the frequent need for this. The issue is simple: I have a JSON data structure that is quoted within a string, and I want to &amp;ldquo;unquote&amp;rdquo; it and filter the JSON so that I can read it.&lt;/p&gt;
&lt;p&gt;So I thought I&amp;rsquo;d spend today restarting the Dequoter project. The best way to describe it is &lt;a href=&#34;https://github.com/IvanMathy/Boop&#34;&gt;a Boop clone&lt;/a&gt;. I like Boop, I use Boop. And I know Boop is extendable, so I could implement any processor I need using JavaScript. But I&amp;rsquo;m not a huge fan of JavaScript, and Go has the function I need &lt;a href=&#34;https://pkg.go.dev/strconv@go1.25.1#Unquote&#34;&gt;right there in the standard library&lt;/a&gt;. And with most things I encounter, I want to build my own. I know I shouldn&amp;rsquo;t, and I&amp;rsquo;ve been better at resisting. But I&amp;rsquo;d figured this could be a nice little distraction. And I thought I could get much of what I need done in a morning.&lt;/p&gt;
&lt;p&gt;So I started a new &lt;a href=&#34;https://wails.io&#34;&gt;Wales project&lt;/a&gt; and after about 3 hours, I had a scratchpad with an invokable command palette that I can use to dequote a string and format a JSON object:&lt;/p&gt;
&lt;p&gt;&lt;video src=&#34;https://cdn.uploads.micro.blog/25293/2025/cleanshot-2025-09-06-at-15.57.26.mp4&#34; poster=&#34;https://lmika.org/uploads/2025/ecf16f805a.png&#34; controls=&#34;controls&#34; preload=&#34;metadata&#34;&gt;&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;Granted, it&amp;rsquo;s not much for 3 hours. While I did use Claude Code a little, much of this was hand rolled. And I spent a lot of time learning the ins and outs of &lt;a href=&#34;https://codemirror.net&#34;&gt;Code Mirror&lt;/a&gt;. This is why I wanted to use Wales this time around. The &lt;a href=&#34;https://lmika.org/2024/07/20/continuing-my-exploration.html&#34;&gt;previous run at this&lt;/a&gt; used &lt;a href=&#34;https://fyne.io/&#34;&gt;Fyne&lt;/a&gt;, which was really nice to use, but the available widgets were quite limited. The nice thing about Wales is that I can build the UI in HTML and it uses the built-in HTML renderer from the OS: no need to bundle Chrome. The frontend is mainly vanilla HTML and JavaScript, although I am using &lt;a href=&#34;https://stimulus.hotwired.dev&#34;&gt;Stimulus&lt;/a&gt; to help with some of the controls. The backend is, of course, Go.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&#34;https://cdn.uploads.micro.blog/25293/2025/cleanshot-2025-09-06-at-15.46.43.png&#34; width=&#34;400&#34; height=&#34;572&#34; alt=&#34;Auto-generated description: Window displaying file information for an application named dequoter, including details like size, location, and version.&#34;&gt;
&lt;figcaption&gt;Final build size is 8.4 MB.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;By the end of this morning&amp;rsquo;s session, what I had was not pretty, but it&amp;rsquo;s functional and it already does what I need it to do. I do have some plans for integrating this with UCL, and using that to define processors. That should hopefully leave all the heavy core stuff to be built near the beginning, and that could sit pretty while the extensions are added in a nicer language. Anyway, more on this if this goes anywhere.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2025/09/04/github-gopher-hawaiian-shirts-patterns.html</link>
      <pubDate>Thu, 04 Sep 2025 08:56:27 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2025/09/04/github-gopher-hawaiian-shirts-patterns.html</guid>
      <description>&lt;p&gt;🔗 &lt;a href=&#34;https://github.com/rsc/gophershirt&#34;&gt;GitHub: Gopher Hawaiian Shirts&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Patterns for printing Hawaiian shirts with the Go gopher. I think I&amp;rsquo;ve found what I&amp;rsquo;ll be wearing to work in the future. 😄&lt;/p&gt;
&lt;p&gt;Via: &lt;a href=&#34;https://golangweekly.com/issues/568&#34;&gt;Golang Weekly&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2025/08/15/dear-go-developers-you-dont.html</link>
      <pubDate>Fri, 15 Aug 2025 06:26:35 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2025/08/15/dear-go-developers-you-dont.html</guid>
      <description>&lt;p&gt;Dear Go developers,&lt;/p&gt;
&lt;p&gt;You don&amp;rsquo;t need to return pointers,&lt;br&gt;
Unless you do need to return pointers.&lt;br&gt;
But if you think you need to return pointers,&lt;br&gt;
You probably don&amp;rsquo;t need to return pointers.&lt;/p&gt;
&lt;p&gt;Instead, consider just returning regular struct values. Keep the nil-pointer panics at bay.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2025/08/07/the-exhaustive-go-linter-complaining.html</link>
      <pubDate>Thu, 07 Aug 2025 16:08:25 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2025/08/07/the-exhaustive-go-linter-complaining.html</guid>
      <description>&lt;p&gt;The &lt;code&gt;exhaustive&lt;/code&gt; Go linter complaining about missing cases for switch statements with a &lt;code&gt;default&lt;/code&gt; clause is killing me.&lt;/p&gt;

  &lt;blockquote&gt;
    &lt;p&gt;missing cases in switch of type this, and this, and this, and this, and…&lt;/p&gt;

  &lt;/blockquote&gt;
&lt;img src=&#34;https://cdn.uploads.micro.blog/25293/2025/out-20250807-160348.jpg&#34; width=&#34;600&#34; height=&#34;328&#34; alt=&#34;Auto-generated description: A man in an office setting sits on a couch next to a bottle, with the text That&#39;s what the default is for.&#34;&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2025/08/05/request-for-a-go-linter.html</link>
      <pubDate>Tue, 05 Aug 2025 11:24:24 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2025/08/05/request-for-a-go-linter.html</guid>
      <description>&lt;p&gt;Request for a go linter: something that would warn when an variable with the name &lt;code&gt;err&lt;/code&gt; is not of type &lt;code&gt;error&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Bla&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;123&lt;/span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// &amp;#39;err&amp;#39; not of type &amp;#39;error&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Would&amp;rsquo;ve saved me a few hours today trying to test if a Future was not-nil, without actually waiting for the result.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Moan-routine: LO&#39;s Predicate Signatures</title>
      <link>https://lmika.org/2025/07/11/moanroutine-los-predicate-signatures.html</link>
      <pubDate>Fri, 11 Jul 2025 17:05:45 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2025/07/11/moanroutine-los-predicate-signatures.html</guid>
      <description>&lt;p&gt;I wish I liked using &lt;a href=&#34;https://github.com/samber/lo&#34;&gt;lo&lt;/a&gt;. People at work swear by it but whenever I use it, I just get annoyed at how much better it could be.&lt;/p&gt;
&lt;p&gt;For those unaware of what &lt;code&gt;lo&lt;/code&gt; is, it&amp;rsquo;s a Go package inspired by &lt;a href=&#34;https://lodash.com&#34;&gt;lodash&lt;/a&gt;, the utility library for JavaScript that allows one to use higher-order functions for operating over collections. Think mapping, filtering, etc. Given that &lt;code&gt;lodash&lt;/code&gt; is built for JavaScript, it&amp;rsquo;s allows for a lot of flexibility in the closures passed to the various functions. &lt;code&gt;map&lt;/code&gt;, for instance, allows a closure that takes two arguments which, when used with an array, will be set to each item&amp;rsquo;s value and index. If you need both bits of information, define a closure with two arguments. If you just need the value, just use one.&lt;/p&gt;
&lt;p&gt;Given Go&amp;rsquo;s strong type system, this flexibility is not granted to us Go developers. Whatever the closure signature is defined for &lt;a href=&#34;https://pkg.go.dev/github.com/samber/lo#Map&#34;&gt;Map&lt;/a&gt; or &lt;a href=&#34;https://pkg.go.dev/github.com/samber/lo#Map&#34;&gt;Filter&lt;/a&gt; is the one you&amp;rsquo;re stuck with (well, that&amp;rsquo;s not entirely true, but more on that in a bit). So it&amp;rsquo;s important for the library developer to come up with some good defaults.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m sure the developer of &lt;code&gt;lo&lt;/code&gt; was trying to be helpful by defining &lt;code&gt;Map&lt;/code&gt; and &lt;code&gt;Filter&lt;/code&gt;  to accept a closure that takes the item&amp;rsquo;s  value and index. But by doing so, they totally screwed me over for the simple reason in that they&amp;rsquo;re not consistent. I can&amp;rsquo;t pass the same function into both &lt;code&gt;Filter&lt;/code&gt; and &lt;a href=&#34;https://pkg.go.dev/github.com/samber/lo#EveryBy&#34;&gt;EveryBy&lt;/a&gt; , as the latter does not accept a closure with an index.&lt;/p&gt;
&lt;p&gt;This prevents me from predefining a set of predicates that I can reused. Being able to define a closure in Go is nice, but you know what&amp;rsquo;s better? Not having to define a closure. Riddle me this: which of these is nicer to read? This:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;isRect&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;shape&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Shape&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;shape&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;corners&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;doThingsWithShapes&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;shapes&lt;/span&gt; []&lt;span style=&#34;color:#a6e22e&#34;&gt;Shape&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;rects&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;lo&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Filter&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;shapes&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;isRect&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;areAllRects&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;lo&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;EveryBy&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;shapes&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;isRect&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or this?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;doThingsWithShapes&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;shapes&lt;/span&gt; []&lt;span style=&#34;color:#a6e22e&#34;&gt;Shape&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;rects&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;lo&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Filter&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;shapes&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;shape&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Shape&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;shape&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;corners&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;areAllRects&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;lo&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;EveryBy&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;shapes&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;shape&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Shape&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;shape&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;corners&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Moot point, as the first one is impossible.&lt;/p&gt;
&lt;p&gt;The mistake of &lt;code&gt;Map&lt;/code&gt; providing two arguments is subtler. When I&amp;rsquo;m operating on a database, I&amp;rsquo;m usually find myself having to map from the types generated from &lt;a href=&#34;https://sqlc.dev&#34;&gt;sqlc&lt;/a&gt; into my own models. Moving this logic out into a separate function makes sense, one that I can invoke when I&amp;rsquo;m dealing with a result set — in which case I could pass this mapping function to &lt;code&gt;Map&lt;/code&gt; — or a single row — in which case I just call function directly. But requiring the &lt;code&gt;Map&lt;/code&gt; closure to take the index screws me here too. I could defining a mapping function that accepts an index that I won&amp;rsquo;t use, but that just makes the direct calls look rubbish. Am I just going to pass in 0 here? Urgh!&lt;/p&gt;
&lt;p&gt;Now, I alluded to the function signatures potentially being a little more flexible. One could use the method of &lt;a href=&#34;https://en.wikipedia.org/wiki/Currying&#34;&gt;currying&lt;/a&gt; which will return a function that will take the first argument and ignore the second. This could allow the same predicate to be used in both &lt;code&gt;Filter&lt;/code&gt; and &lt;code&gt;EveryBy&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ignoreSecondArg&lt;/span&gt;[&lt;span style=&#34;color:#a6e22e&#34;&gt;T&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;U&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;V&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;any&lt;/span&gt;](&lt;span style=&#34;color:#a6e22e&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;T&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;V&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;T&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;U&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;V&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;T&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;U&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;V&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;fn&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;isRect&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;shape&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Shape&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;shape&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;corners&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;doThingsWithShapes&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;shapes&lt;/span&gt; []&lt;span style=&#34;color:#a6e22e&#34;&gt;Shape&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;rects&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;lo&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Filter&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;shapes&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;ignoreSecondArg&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;isRect&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;areAllRects&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;lo&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;EveryBy&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;shapes&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;isRect&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It would&amp;rsquo;ve been nice for &lt;code&gt;lo&lt;/code&gt; to provided these functions. The closest I see are the &lt;a href=&#34;https://pkg.go.dev/github.com/samber/lo#Partial&#34;&gt;Partial&lt;/a&gt; functions which &lt;em&gt;almost&lt;/em&gt; do what I need. Yet they&amp;rsquo;re designed for pegging the first argument to a value and returning a function that takes the second one. I&amp;rsquo;ve have no need for these sorts of function, and having something which could help in adapting these predicates would seem much more useful to me.&lt;/p&gt;
&lt;p&gt;(Deep breath)&lt;/p&gt;
&lt;p&gt;Okay, I can see how this all looks a little unfair. And I&amp;rsquo;m not going to say the developer or users are making mistakes here. Well, I am, but I&amp;rsquo;m not say that they&amp;rsquo;re incompetent or have malicious intent. I&amp;rsquo;m sure there are good reasons behind these decisions.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s just… this could be so much better than it currently is. Consider this criticism from someone who&amp;rsquo;d like to see this package succeed, like a parent or a coach trying to help a struggling child. We&amp;rsquo;re not using JavaScript here; we&amp;rsquo;re bound to the type system we have. Embrace that. Recognise that the occasional closure is fine but can get unwieldily whenever we&amp;rsquo;re forced to make one with one of your functions. The flexibility you provide here is an example of the perfect being the enemy of the good.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2025/06/25/theres-no-reason-to-use.html</link>
      <pubDate>Wed, 25 Jun 2025 11:35:30 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2025/06/25/theres-no-reason-to-use.html</guid>
      <description>&lt;p&gt;There&amp;rsquo;s no reason to use &lt;a href=&#34;https://pkg.go.dev/github.com/stretchr/testify/suite&#34;&gt;Testify&amp;rsquo;s Suite package&lt;/a&gt; for Go unit tests anymore. It&amp;rsquo;s possible to do whatever you need to do with Go&amp;rsquo;s builtin test runner. Furthermore, most IDEs are smart enough to detect and run sub-tests that use &lt;code&gt;t.Run()&lt;/code&gt;. So save yourself some trouble and just use the defaults.&lt;/p&gt;

  &lt;span class=&#34;clearfix-hack&#34;&gt;&lt;/span&gt;
  &lt;blockquote class=&#34;alert alert-selfreply&#34;&gt;
    &lt;p class=&#34;alert-heading&#34;&gt;
      
    &lt;/p&gt;
    &lt;p&gt;&lt;time datetime=&#34;2025-06-25T01:46:05Z&#34; class=&#34;reply-timestamp&#34;&gt;11:46&lt;/time&gt; I guess my point is that it&amp;rsquo;s nice to be able to run specific unit tests directly from the IDE, and that&amp;rsquo;s difficult to do using the Suite package.&lt;/p&gt;
  &lt;/blockquote&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2025/05/13/does-google-ever-regret-naming.html</link>
      <pubDate>Tue, 13 May 2025 08:18:40 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2025/05/13/does-google-ever-regret-naming.html</guid>
      <description>&lt;p&gt;Does Google ever regret naming Go &amp;ldquo;Go&amp;rdquo;? Such a common word to use as a proper noun. I know the language devs prefer not to use Golang, but there&amp;rsquo;s no denying that it&amp;rsquo;s easier to search for.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2024/12/18/lot-of-interesting.html</link>
      <pubDate>Wed, 18 Dec 2024 15:06:49 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2024/12/18/lot-of-interesting.html</guid>
      <description>&lt;p&gt;Lot of interesting thing scheduled for &lt;a href=&#34;https://tip.golang.org/doc/go1.24&#34;&gt;Go 1.24&lt;/a&gt;, but this one looks particularly exciting:&lt;/p&gt;

  &lt;blockquote&gt;
    &lt;p&gt;The new &lt;a href=&#34;https://tip.golang.org/pkg/crypto/rand#Text&#34;&gt;Text&lt;/a&gt; function can be used to generate cryptographically secure random text strings.&lt;/p&gt;

  &lt;/blockquote&gt;
&lt;p&gt;You&amp;rsquo;d be surprised how often I need to generate random strings. Doing so, without installing a third-party package, is always a bit involved; either generating a UUID and stripping the dashes, or doing a Base64 on a random byte slice. To be given a function to do this from the standard library will be most welcome.&lt;/p&gt;

  &lt;span class=&#34;clearfix-hack&#34;&gt;&lt;/span&gt;
  &lt;blockquote class=&#34;alert alert-selfreply&#34;&gt;
    &lt;p class=&#34;alert-heading&#34;&gt;
      
    &lt;/p&gt;
    &lt;p&gt;&lt;time datetime=&#34;2024-12-18T05:09:19Z&#34; class=&#34;reply-timestamp&#34;&gt;16:09&lt;/time&gt; And yes, I know generating a UUID usually involves installing a package (it&amp;rsquo;s high time Go&amp;rsquo;s standard library included a UUID implementation IMHO), but it&amp;rsquo;s usually a package I import anyway. Either that, or &lt;a href=&#34;https://github.com/matoous/go-nanoid&#34;&gt;go-nanoid&lt;/a&gt;.&lt;/p&gt;
  &lt;/blockquote&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2024/10/16/golands-llmpowered-auto.html</link>
      <pubDate>Wed, 16 Oct 2024 12:39:04 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2024/10/16/golands-llmpowered-auto.html</guid>
      <description>&lt;p&gt;Goland&amp;rsquo;s LLM-powered auto-complete is really good. It&amp;rsquo;s got to the point where it feels like Goland is broken when I&amp;rsquo;m using a version that doesn&amp;rsquo;t have it. I&amp;rsquo;m sure they hope to expand of this, and if I can make a request on what they could do next, it would be to add &amp;ldquo;auto-complete&amp;rdquo; suggestions in other areas of the code.&lt;/p&gt;
&lt;p&gt;For example, I&amp;rsquo;m working on a function which uses AWS&amp;rsquo;s Golang SDK to send an SQS message. I started writing out the call to send a message, when I found out that I forgot to define both the &lt;a href=&#34;https://pkg.go.dev/context&#34;&gt;context&lt;/a&gt; and queue name in the function I&amp;rsquo;m working in. Nothing too hard to fix, of course, but it would mean moving away from where I&amp;rsquo;m am now, and conducting a mini context-switch away from calling the SDK to fixing my function definition.&lt;/p&gt;
&lt;p&gt;It would be nice for the LLM-based auto-completer to suggest adding the context as the first parameter of the function, as per the convention. The queue name is a little more ambiguous: it could either be suggested as another function parameter or as a field on the provider type. I suppose both are just as likely, but assuming that Goland is refining it&amp;rsquo;s model based on my trends, it could suggest adding the topic name as a field, along with adding it in as a parameter to the constructor function.&lt;/p&gt;
&lt;p&gt;Anyway, something for them to look at when they run out of work.&lt;/p&gt;

  &lt;span class=&#34;clearfix-hack&#34;&gt;&lt;/span&gt;
  &lt;blockquote class=&#34;alert alert-selfreply&#34;&gt;
    &lt;p class=&#34;alert-heading&#34;&gt;
      
    &lt;/p&gt;
    &lt;p&gt;&lt;time datetime=&#34;2024-10-16T02:42:21Z&#34; class=&#34;reply-timestamp&#34;&gt;13:42&lt;/time&gt; I mean, to be fair, they do offer &amp;ldquo;quick fixes&amp;rdquo; like creating a field when I reference one that doesn&amp;rsquo;t exist. They just need to take the next step and outright suggest it as a change, rather than have me write out the missing field, click the type error, and select the fix from the menu.&lt;/p&gt;
  &lt;/blockquote&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2024/10/09/please-go-developers.html</link>
      <pubDate>Wed, 09 Oct 2024 14:49:23 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2024/10/09/please-go-developers.html</guid>
      <description>&lt;p&gt;Please, Go developers, do not use Testify&amp;rsquo;s &lt;a href=&#34;https://pkg.go.dev/github.com/stretchr/testify/suite&#34;&gt;suite&lt;/a&gt; package. There&amp;rsquo;s not much support for the de-facto &lt;a href=&#34;https://dev.to/ankitmalikg/how-to-write-unit-test-cases-for-golang-3ln0#tabular-test-case&#34;&gt;tabular test pattern&lt;/a&gt;, where you have tests nested within tests. Plus, it lacks any IDE integration niceties, such as running specific scenarios. Just use the &lt;a href=&#34;https://pkg.go.dev/testing&#34;&gt;built-in test package&lt;/a&gt;.&lt;/p&gt;

  &lt;span class=&#34;clearfix-hack&#34;&gt;&lt;/span&gt;
  &lt;blockquote class=&#34;alert alert-selfreply&#34;&gt;
    &lt;p class=&#34;alert-heading&#34;&gt;
      
    &lt;/p&gt;
    &lt;p&gt;&lt;time datetime=&#34;2024-10-09T05:06:42Z&#34; class=&#34;reply-timestamp&#34;&gt;16:06&lt;/time&gt; Nothing wrong with the Testify project itself, mind you. I use the assert package all the time. But the suite package just doesn&amp;rsquo;t gel with how unit testing is traditionally done in Go.&lt;/p&gt;
  &lt;/blockquote&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2024/04/11/buffalo-the-go.html</link>
      <pubDate>Thu, 11 Apr 2024 16:36:32 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2024/04/11/buffalo-the-go.html</guid>
      <description>&lt;p&gt;Buffalo, the Go framework that&amp;rsquo;s a bit like Rails, has been archived on GitHub. I&amp;rsquo;m wondering if it&amp;rsquo;s been retired. I&amp;rsquo;ve seen no announcement but I&amp;rsquo;m starting to suspect that it has.&lt;/p&gt;
&lt;p&gt;A real shame. It was pretty good and the dev was so passionate behind it. Maybe running it was just too much.&lt;/p&gt;

  &lt;span class=&#34;clearfix-hack&#34;&gt;&lt;/span&gt;
  &lt;blockquote class=&#34;alert alert-selfreply&#34;&gt;
    &lt;p class=&#34;alert-heading&#34;&gt;
      
    &lt;/p&gt;
    &lt;p&gt;&lt;time datetime=&#34;2024-04-11T06:41:29Z&#34; class=&#34;reply-timestamp&#34;&gt;16:41&lt;/time&gt; I may need to rebuild Alto because of this. I was considering doing so anyway, just to make it simpler to maintain (I&amp;rsquo;m kinda afraid to touch it at the moment).&lt;/p&gt;
  &lt;/blockquote&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2024/04/08/dealing-with-money.html</link>
      <pubDate>Mon, 08 Apr 2024 17:23:33 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2024/04/08/dealing-with-money.html</guid>
      <description>&lt;p&gt;Dealing with money is annoying. Dealing with money using Go&amp;rsquo;s &lt;code&gt;big.Rat&lt;/code&gt; type? Really annoying.😮‍💨&lt;/p&gt;

  &lt;span class=&#34;clearfix-hack&#34;&gt;&lt;/span&gt;
  &lt;blockquote class=&#34;alert alert-selfreply&#34;&gt;
    &lt;p class=&#34;alert-heading&#34;&gt;
      
    &lt;/p&gt;
    &lt;p&gt;&lt;time datetime=&#34;2024-04-08T07:57:40Z&#34; class=&#34;reply-timestamp&#34;&gt;17:57&lt;/time&gt; I complain, but dealing with Go&amp;rsquo;s weird API for big.Rat still beats flaffing about with formulas in Numbers.&lt;/p&gt;
  &lt;/blockquote&gt;
</description>
    </item>
    
    <item>
      <title>Broadtail</title>
      <link>https://lmika.org/2024/01/24/broadtail.html</link>
      <pubDate>Wed, 24 Jan 2024 02:10:00 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2024/01/24/broadtail.html</guid>
      <description>&lt;p&gt;&lt;strong&gt;Date:&lt;/strong&gt; 2021 – 2022&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Status:&lt;/strong&gt; Paused&lt;/p&gt;
&lt;p&gt;First project I&amp;rsquo;ll talk about is Broadtail. I think I talked about this
one before, or at least I posted screenshot of it. I started work on
this in 2021. The pandemic was still raging, and much of my downtime was
watching YouTube videos. We were coming up to a federal election, and I
was getting frustrated with seeing YouTube ads from political parties
that offend me. This was before YouTube Premium so there was no real way
to avoid these ads. Or was there?&lt;/p&gt;
&lt;h3 id=&#34;a-frontend-for-youtube-dl&#34;&gt;A Frontend For youtube-dl&lt;/h3&gt;
&lt;p&gt;I had some experience with youtube-dl in the past, downloading and
saving videos that I hoped to watch later. I recently discovered that
YouTube also published RSS feeds for channels and playlist. So I was
wondering if it was possible to build something that could use both of
these. My goal was to have something that would allow me to subscribe to
YouTube channels via RSS, download videos using youtube-dl, and watch
them via Plex on my TV. This was to be deployed on a Intel Nuc that I
was using as a home server, and be accessible via the web-browser.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&#34;https://cdn.uploads.micro.blog/25293/2024/db017f8413.jpg&#34;&gt;
&lt;figcaption&gt;An early version of Broadtail, with only the download frontend.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;I deceided to get the YouTuble downloading feature built first. I
started a new Go project and got something up and running reasonably
quickly. It was a good excuse to get back to vanilla Go web development,
using http.Handle and Go templates, instead of relying on frameworks
like Buffalo (don&amp;rsquo;t get me wrong, I still like Buffalo, but it is quite
heavy handed).&lt;/p&gt;
&lt;p&gt;It was also an excuse to try out StormDB, which is an embedded NoSQL
data store. The technology behind it is quite good — it&amp;rsquo;s used B-Trees
memory mapped files under the cover — and I tend to use it for other
things as well. It proved to be quite usable, apart from not allowing
multiple read/writers at the same time, which made deployments
difficult.&lt;/p&gt;
&lt;p&gt;But the backend code was the easy part. What I lack was any sense of web
design. That&amp;rsquo;s one good thing about a framework like Buffalo: it comes
with a usable style framework out of the box (Bootstrap). If I were to
go my own way, I&amp;rsquo;d have to start from scratch.&lt;/p&gt;
&lt;p&gt;The other side of that coin though, is that it would give me the freedom
to go for something that&amp;rsquo;s slightly off-beat. So I went for an
aesthetics that reminded me of early 2000 web-design: san-serif font,
all grey lines, dull pastels colours, small controls and widgets (I
stopped short at gradients and table-based layouts).&lt;/p&gt;
&lt;p&gt;This version also included a hand-rolled job manager that I used for a
bunch of other things. It&amp;rsquo;s… fine. I wouldn&amp;rsquo;t use it for anything
&amp;ldquo;real&amp;rdquo;, but it had a way of managing job lifecycles, updating
progress, and the ability to cancel a running job. So for that, it was
good enough.&lt;/p&gt;
&lt;p&gt;Finally, it needed a name. At the time, I was giving all projects
bird-like codename, since I can&amp;rsquo;t come up with names that I liked. I
eventually settled on Broadtail, which was a reference to &lt;a href=&#34;https://en.wikipedia.org/wiki/Broad-tailed_parrot&#34;&gt;broadtail
parrots&lt;/a&gt;, like the rosella.&lt;/p&gt;
&lt;h3 id=&#34;rss-subscriptions&#34;&gt;RSS Subscriptions&lt;/h3&gt;
&lt;p&gt;It didn&amp;rsquo;t take long after I got this up and running before I realised I
needed the RSS subscription feature. So that was the next thing I
added.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&#34;https://cdn.uploads.micro.blog/25293/2024/02c7ec1b20.jpg&#34;&gt;
&lt;figcaption&gt;Homepage of the most recent version of Broadtail, with an active
download and a couple of favourited items.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;That way it worked was pretty straight forward. One would setup a
subscription to a YouTube channel or playlist. Broadtail will then poll
that RSS subscription every 15 minutes or so, and show new videos on the
homepage. Clicking that video item would bring up details and an option
to download it.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&#34;https://cdn.uploads.micro.blog/25293/2024/7811391b7b.jpg&#34;&gt;
&lt;figcaption&gt;Video details. This one is simulated as I couldn&#39;t get youtube-dl working.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Each RSS subscription had an associated target directory. Downloading an
ad-hoc video would just dump it in a configured directory but I wanted
to make it possible to organise downloads from feeds in a more
structured way. This wasn&amp;rsquo;t perfect though: I can&amp;rsquo;t remember the
reason but I had some trouble with this, and most videos just ended up
in the download directory by default (it may have had to do with making
directories or video permissions).&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&#34;https://cdn.uploads.micro.blog/25293/2024/7b51bf5401.jpg&#34;&gt;
&lt;figcaption&gt;Click a feed to view the most recent items.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Only the feed polling was automatic at this stage. I was not interested
in having all shows downloaded, as that would eat up on bandwidth and
disk storage. So users still had to choose which videos they wanted to
download. The list of recent feed items were available from the
home-screen so they were able to just do so from there.&lt;/p&gt;
&lt;p&gt;I also wanted to keep abreast with what jobs were currently running, so
the home-screen also had the list of running job.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&#34;https://cdn.uploads.micro.blog/25293/2024/6869f68642.jpg&#34;&gt;
&lt;figcaption&gt;Click the job to view it&#39;s details. This one failed.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The progress-bar was powered by a web-socket backed by a goroutine on
the server side, which meant realtime updates. Clicking the job would
also show you the live output of the youtube-dl command, making it easy
to troubleshoot any jobs that failed. Jobs could be cancelled at any
time, but one annoying thing that was missing was the ability to retry
failed job. If a download failed, you had to spin up a new job from
scratch. This meant clearing out the old job from the file-system and
finding the video ID again from wherever you found it.&lt;/p&gt;
&lt;p&gt;If you were interested in a video but were not quite ready to download
it right away, you could &amp;ldquo;favourite&amp;rdquo; it by clicking the star. This was
available in every list that showed a video, and was a nightmare to code
up, since I was keeping references to where the video came from, such as
a feed or a quick look. Keeping atop of all the possible references were
become difficult with the non-relational StormDB, and the code that
handled this became quite dodgy (the biggest issue was dealing with
favourites from feeds that were deleted).&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&#34;https://cdn.uploads.micro.blog/25293/2024/c975ebbac0.jpg&#34;&gt;
&lt;figcaption&gt;Clicking &#34;Favourites&#34; would show the items that you starred.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&#34;rules--wwdc-videos&#34;&gt;Rules &amp;amp; WWDC Videos&lt;/h3&gt;
&lt;p&gt;The basics were working out quite well, but it was all so manual. Plus,
going from video publication to having something to watch was not
timely. The RSS feed from YouTube was always several hours out of date,
and downloading whole videos took quite a while (it may not have been
realtime, but it was pretty close).&lt;/p&gt;
&lt;p&gt;So one of the later things I added was a feature I called &amp;ldquo;Rules&amp;rdquo;.
These were automations that would run when the RSS feed was polled, and
would automatically download videos that met certain criteria (you could
also hide them or mark them as downloaded). I quite enjoy building these
sorts of complex features, where the user is able to do configure
sophisticated automatic tasks, so this was a fun thing to code up. And
it worked: video downloads would start when they become available and
would usually be in Plex when I want to watch it (it was also possible
to ping Plex to update the library once the download was finished). It
wasn&amp;rsquo;t perfect though: not retrying failed downloads did plague it a
little. But it was good enough.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&#34;https://cdn.uploads.micro.blog/25293/2024/619c14dab2.jpg&#34;&gt;
&lt;figcaption&gt;Editing a Rule.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;This was near the end of my use of Broadtail. Soon after adding Rules, I
got onto the YouTube Premium bandwagon, which hid the ads and removed
the need for Broadtail as a whole. It was a good thing too, as the Plex
Android app had this annoying habit of causing the Chrome Cast to hang,
and the only way to recover from this was to reboot the device.&lt;/p&gt;
&lt;p&gt;So I eventually returned to just using YouTube, and Broadtail was
eventually abandoned.&lt;/p&gt;
&lt;p&gt;Although, not completely. One last thing I did was extend Broadtail&amp;rsquo;s
video download capabilities to include Apple WWDC Videos. This was
treated as a special kind of &amp;ldquo;feed&amp;rdquo; which, when polled, would scrap
the WWDC video website. I was a little uncomfortable doing this, and I
knew when videos were published, they wouldn&amp;rsquo;t change. So this &amp;ldquo;feed&amp;rdquo;
was never polled and the user had to refresh it automatically.&lt;/p&gt;
&lt;p&gt;Without the means to stream them using AirPlay, downloading them and
making them available in Plex was the only way I knew of watching them
on my TV, which is how I prefer to watch them.&lt;/p&gt;
&lt;p&gt;So that&amp;rsquo;s what Broadtail is primarily used for now. It&amp;rsquo;s no longer
running as a daemon: I just boot it up when I want to download new
videos. And although it&amp;rsquo;s only a few years old, it&amp;rsquo;s starting to show
signs of decay, with the biggest issue being youtube-dl slowly being
abandoned.&lt;/p&gt;
&lt;p&gt;So it&amp;rsquo;s unlikely that I&amp;rsquo;ll put any serious efforts into this now. But
if I did, there are a few things I&amp;rsquo;d like to see:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Authentication added with username/password&lt;/li&gt;
&lt;li&gt;Retry failed video downloads.&lt;/li&gt;
&lt;li&gt;The ability to download YouTube videos in audio only (all these
&amp;ldquo;podcasts&amp;rdquo; that are only available as YouTube videos… 😒)&lt;/li&gt;
&lt;li&gt;The ability to handle the lifecycle of videos a little better than it
does now. It&amp;rsquo;s already doing this for errors: when a download fails,
the video is deleted. But it would be nice if it did things like
automatically delete videos 30 days after downloading them. This would
require more control over the &amp;ldquo;video store&amp;rdquo; though.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, that&amp;rsquo;s Broadtail.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://lmika.org/2021/06/26/why-i-like.html</link>
      <pubDate>Sat, 26 Jun 2021 08:26:00 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2021/06/26/why-i-like.html</guid>
      <description>&lt;p&gt;Why I like developing in Go vs. something like NodeJS: my development setup doesn&amp;rsquo;t randomly break for some weird reason.  When it does break, it&amp;rsquo;s because of something I did explicitly.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Why I&#39;m Considering Building A Blogging CMS</title>
      <link>https://lmika.org/2020/11/19/on-building-vs.html</link>
      <pubDate>Thu, 19 Nov 2020 08:29:00 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2020/11/19/on-building-vs.html</guid>
      <description>&lt;p&gt;I&amp;rsquo;m planning to start a new blog about Go development and one of the things that I&amp;rsquo;m currently torn on is how to host it.  The choice look to be either using a service like &lt;a href=&#34;https://blot.im/&#34;&gt;blot.im&lt;/a&gt; or &lt;a href=&#34;https://micro.blog/&#34;&gt;micro.blog&lt;/a&gt; or some other hosting service, using a static site generation tool like &lt;a href=&#34;https://gohugo.io&#34;&gt;Hugo&lt;/a&gt;, or building my own CMS for it.  I know that one of the things people tell you about blogging is that building your CMS is not worth your time: I myself even described it as &amp;ldquo;second cardinal sin of programming&amp;rdquo; on my &lt;a href=&#34;https://lmika.micro.blog/2020/07/12/ive-signed-up.html&#34;&gt;first post to micro.blog&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Nevertheless, I think at this stage I will actually do just that.  Despite the effort that comes from building a CMS I see some advantages in doing so:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;The (theoretical) ability to blog from anywhere:&lt;/strong&gt;  This is one of the weaknesses of static site hosting that I&amp;rsquo;ve run into when trying this approach before.  I tend to work on different machines throughout the week, which generally means that when I find inspiration, I don&amp;rsquo;t have the source files on hand to work on them.  The source files are kept in source control and are hosted on GitHub, but I&amp;rsquo;ve find that I tend to be quite lax with making sure I have the correct version checked out and that any committed changes are pushed.  This is one of the reasons why I like micro.blog: having a service with a web interface that I can just log into, and that will have all the posts there, means that I can work on them as long as I have an internet connection.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Full control over the appearance and workflow:&lt;/strong&gt; Many of the other services provide the means for adjusting the appearance of the web-page, so this is only a minor reason for taking on this effort.  But one thing that I would find useful is to have some control over is the blogging workflow itself.  There are some ideas that I might like to include, like displaying summaries in the main page, or sharing review links for posts prior to publishing them.  Being able to easily do that in a codebase that I&amp;rsquo;m familiar with would help.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Good practice of my skills:&lt;/strong&gt; As someone who tends to work on backend systems for his day-to-day job, some of my development and operational experience are a little rusty.  Building, hosting and operating a site would provide an opportunity to exercise these muscles, and may also come in handy if I were to choose to build something for others to use (something that I&amp;rsquo;ve been contemplating for a while).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Note that price is not one of these reasons.  In fact it might actually cost me a little more to put together a site like this.  But I think the experience and control that I hope to get out of this endeavour might be worth it.&lt;/p&gt;
&lt;p&gt;I am also aware of some of the risks of this approach.  Here is how I plan to mitigate them:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Security and stability:&lt;/strong&gt; This is something that comes for free from a blogging platform that I&amp;rsquo;ll need to take on myself.  There&amp;rsquo;s always a risk with putting a new system onto the internet, and having a web site with remote administration is an invitation for others to abuse it.  To me this is another area of development I believe I need to work on.  Although I don&amp;rsquo;t intend to store any personal information but my own, I do have to be mindful of the risks of putting anything online, and making sure that the appropriate mitigations are in place to prevent that.  I&amp;rsquo;ll also have to make sure that I&amp;rsquo;m maintaining proper backups of the content, and periodically exercising them to make sure they work.  The fact that my work is at stake is a good incentive to keep on top of this.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Distractions:&lt;/strong&gt; Yeah, this is a classic problem with me: I use something that I build, I find a small problem or something that can be improved, then instead of actually finishing the task, I actually work on the code for the service.  This may have to be something that only gets addressed with discipline.  It may help using the CMS on a machine that doesn&amp;rsquo;t have the source code.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I will also have to be aware of the amount of time I put into this.  I actually started working on a CMS several months ago so I&amp;rsquo;m not starting completely from scratch, but I&amp;rsquo;ve learnt with too many other of my personal projects that maintaining something like this is for the long term.  It might be fine to occasionally tinker with it, but I cannot spend too much effort working on the system at the expense of actually writing content.&lt;/p&gt;
&lt;p&gt;So this is what I might do.  I might give myself the rest of the month to do what I need to do to get it up to scratch, then I will start measuring how much time I spend working on it, vs. the amount of time I actually use it to write content.  If the time I spend working on the code base is more than 50% of time I use it to write content, then it will indicate to me that it&amp;rsquo;s a distraction and I will abandon it for an alternative setup.  To keep myself honest, I&amp;rsquo;ll post the outcomes of this on my micro blog (if I remember).&lt;/p&gt;
&lt;p&gt;A few other minor points:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Will this delay publishing of the blog?  No. The CMS is functionally complete but there are some rough edges that I&amp;rsquo;d like to smooth out.  I hope to actually start publishing this new blog very shortly.&lt;/li&gt;
&lt;li&gt;Will I be moving the hosting of this blog onto the new CMS?  No, far from it. The services here works great for how I want to maintain this blog, and the community aspects are fantastic.  The CMS also lacks the IndiWeb features that micro.blog offers and it may be some time before they get built.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;ll be interested if anyone has any thoughts on this so feel free to reply to this post on micro.blog.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; I&amp;rsquo;ve posted a &lt;a href=&#34;https://lmika.org/2020/12/13/revising-the-decision.html&#34;&gt;follow-up&lt;/a&gt; on this decision about a month after writing this.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Offical support for file embedding coming to Go</title>
      <link>https://lmika.org/2020/10/31/offical-support-for.html</link>
      <pubDate>Sat, 31 Oct 2020 07:50:00 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2020/10/31/offical-support-for.html</guid>
      <description>&lt;p&gt;I&amp;rsquo;m excited to see, via &lt;a href=&#34;https://golangweekly.com/issues/336&#34;&gt;Golang Weekly&lt;/a&gt;, that the &lt;a href=&#34;https://go.googlesource.com/proposal/+/master/design/draft-embed.md&#34;&gt;official support for embedding static files in Go&lt;/a&gt; is being realised, with the &lt;a href=&#34;https://github.com/golang/go/commit/25d28ec55aded46e0be9c2298f24287d296a9e47&#34;&gt;final commit merged to the core a couple of days ago&lt;/a&gt;.  This, along with the &lt;a href=&#34;https://go.googlesource.com/proposal/+/master/design/draft-iofs.md&#34;&gt;new file-system abstraction&lt;/a&gt;, will mean that it will be much easier to embed files in Go applications, and make use of them within the application itself.&lt;/p&gt;
&lt;p&gt;One of the features I like about coding is Go is that the build artefacts are statically linked executables that can be distributed without any additional dependencies.  This means that if I wanted to share something, all I need to do is to give them a single file that they can just run, without needing to worry about whether particular dependencies or runtimes are installed prior to doing so.&lt;/p&gt;
&lt;p&gt;However there are times when the application requires static files, and to maintain this simple form of distribution, I generally want to embed these files within the application itself.  This comes up surprisingly often and is not something that was officially supported within the core language tools, meaning that this gap had to be filled by 3rd parties.  Given the &lt;a href=&#34;https://github.com/golang/go/wiki/Projects#resource-embedding&#34;&gt;number of tools available to do this&lt;/a&gt;, I can see that I&amp;rsquo;m not alone in needing this.  And as great as it is to see the community step in to fill this gap, relying on an external tool complicates the build process a bit&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;: making sure the tool is installed, making sure that it is executed when the build run, making sure that the tool is actively being maintained so that changes to the language will be supported going forward, etc.&lt;/p&gt;
&lt;p&gt;One other thing about these tools is that the API used to access the file is always slightly different as well, meaning that if there&amp;rsquo;s a need to change tools, you end up needing to change your code to actually access the statically embedded file.&lt;/p&gt;
&lt;p&gt;Now that embedding files is officially coming to the language itself, there is less need to rely on all of this.  There&amp;rsquo;s no need to worry about various tools being installed on the machines that are building the application.  And the fact that this feature will work hand in hand with the new file system abstraction means that embedded files would be easier to work with within the code base itself.&lt;/p&gt;
&lt;p&gt;So kudos to the core Go development team.  I&amp;rsquo;m really looking forward to using this.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;Although not as much as many other languages.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Remarks on Go&#39;s Error Handling using Facebook&#39;s SDK Crashes As a Framing Device</title>
      <link>https://lmika.org/2020/07/14/there-are-new.html</link>
      <pubDate>Tue, 14 Jul 2020 08:43:00 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2020/07/14/there-are-new.html</guid>
      <description>&lt;p&gt;There are new &lt;a href=&#34;https://mjtsai.com/blog/2020/07/13/another-facebook-sdk-crash/&#34;&gt;reports of Facebook&amp;rsquo;s SDK crashing apps again&lt;/a&gt; due to server changes.  The post above links to Bugsnag article which explores the underlying cause: that&amp;rsquo;s worth a read.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m going to throw a shout-out to Go&amp;rsquo;s approach to error handling here.  I&amp;rsquo;m not saying that this shows the superiority of Go over Objective C: these sorts of things can happen in any language.  The difference I want to highlight is that Go treats error handling as part of the standard flow of the language, rather than the exceptional flow.  This forces you to think about error conditions when you&amp;rsquo;re making calls to code that can fail.&lt;/p&gt;
&lt;p&gt;This does result in some annoying code of the form:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;result, err := doOperation()
if err != nil {
    return nil, err
}

result2, err := doSecondOperation(result)
if err != nil {
    return nil, err
}

// and so on
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and there&amp;rsquo;s nothing stopping your from completely ignoring the error.&lt;/p&gt;
&lt;p&gt;But there&amp;rsquo;s no way to call these two functions without dealing with the error in some way.  That is, there&amp;rsquo;s no way to simply write &lt;code&gt;doSecondOperation(doOperation())&lt;/code&gt;: you&amp;rsquo;re given an error and you have to do something with it.  So you might as well handle it gracefully.&lt;/p&gt;
&lt;p&gt;P.S. I should probably state that I know very little about Objective C.  I do know that a fair number of APIs in AppKit and UIKit make use of completion handlers which can provide an error value, although to me it seems a littler easier to ignore it vs. deailing with the error values in Go.  I also know that Swift makes improvements here, forcing you to prefix calls that can fail with the &lt;code&gt;try&lt;/code&gt; keyword.  Again, this is not to rag on Objective C; rather it&amp;rsquo;s a comment on the idioms of error handling in Go and how these sort of events could prevent the app from crashing.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>On Go’s Type Parameters Proposal</title>
      <link>https://lmika.org/2020/07/12/on-gos-type.html</link>
      <pubDate>Thu, 25 Jun 2020 11:30:00 +1000</pubDate>
      
      <guid>http://lmika.micro.blog/2020/07/12/on-gos-type.html</guid>
      <description>&lt;p&gt;The developers of Go have release a new draft proposal for type parameters.  The biggest change is the replacing the concept of constraints, which complicated the proposal somewhat, and replaced it with interfaces to express the same thing.  You can read the proposal here &lt;a href=&#34;https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-type-parameters.md&#34;&gt;latest proposal here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I think they’re starting to reach a great balance between what currently exists in the language, and the features required to make a useful type parameter system.  The use of interfaces to constrain the type, that is declare the operators that a type must implement in order to be used as a type parameter for a function or struct, makes total sense.  It also makes moving to type parameters in some areas of the standard library trivial.  For example, the &lt;a href=&#34;https://golang.org/pkg/sort/#Sort&#34;&gt;sort.Sort&lt;/a&gt; function prototype:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;func Sort(data Interface)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;can simply be written as:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;func Sort(type T Interface)(data T)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I do have some minor concerns though.  The biggest one is the use of interfaces to express constraints related to operators, which are expressed as &lt;a href=&#34;https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-type-parameters.md#type-lists-in-constraints&#34;&gt;type lists&lt;/a&gt;.  I think listing the types that a particular type parameter can instantiate makes sense.  It dramatically simplifies the process of expressing a constraint based on the operators a particular type supports.  However, using the concept of interfaces for this purpose seems a little strange, especially so when these interfaces cannot be used in areas &lt;a href=&#34;https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-type-parameters.md#type-lists-in-interface-types&#34;&gt;other than type constraints&lt;/a&gt;.  To be fair, it seems like they recognise this, and I&amp;rsquo;m suspecting that in practice these interfaces will be defined in a package that can simply be used, thereby not requiring us to deal with them directly unless we need to.&lt;/p&gt;
&lt;p&gt;But all in all, this looks promising.  It is starting to feel like the design is coming together, with the rough edges starting to be smoothed out.  I appreciate the level of careful consideration the core Go developers are exhibiting in this process.  This is after all a large change to the language, and they only have one real chance at this.  Sure we have to wait for it, but especially in language design, mistakes are forever.&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>