<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Golang on Geoff Baskwill</title>
    <link>https://geoffbaskwill.ca/tags/golang/</link>
    <description>Geoff Baskwill (Golang)</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-ca</language>
    <lastBuildDate>Thu, 03 Dec 2020 00:00:00 +0000</lastBuildDate>
    
    <atom:link href="https://geoffbaskwill.ca/tags/golang/index.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>Why I Use Go (for now)</title>
      <link>https://geoffbaskwill.ca/posts/why-i-use-go/</link>
      <pubDate>Thu, 03 Dec 2020 00:00:00 +0000</pubDate>
      
      <guid>https://geoffbaskwill.ca/posts/why-i-use-go/</guid>
      <description>&lt;p&gt;Recently someone asked me why I prefer using Go to build services instead of Python.&lt;/p&gt;
&lt;p&gt;It struck me as an odd question, mostly because the way it was phrased and how I skimmed it made me think they were asking why I recommended using Python to build services, which is something I have never done. Once we got past my misunderstanding and I had apologized for not reading carefully, I took a few minutes to think about it.&lt;/p&gt;
&lt;p&gt;The first point to keep in mind is that I would not call myself a competent Python programmer. It is entirely possible that if I were more comfortable with Python, I would pick it up as a tool more often. Some Very Smart People™ I know use Python for Real Services In Production™. I wouldn’t, but as I mentioned, I’m not exactly well-versed. I expect that if I were dropped into an environment where I could learn from those Very Smart People, I might grow to understand why they have made that choice.&lt;/p&gt;
&lt;p&gt;It would be fairer to ask why I use Go instead of Java, as there was a time that I considered myself not-incompetent in Java, and I railed mightily against the project lead who decreed that I would learn Go.&lt;/p&gt;
&lt;p&gt;I use and recommend Go these days because it has a lot of tools for writing robust, predictable, and reliable code, concisely. I have found over the last few years of learning Go that I can write better services than I ever did in Java, and I can do it faster and more easily. The end product is also more performant and more predictable with less effort on my part, not to mention ridiculously small compared to stuff built on the Java Virtual Machine.&lt;/p&gt;
&lt;p&gt;As a tool, Go fits well with the problems that I am trying to solve today.&lt;/p&gt;
&lt;p&gt;Are there things that are annoying and things I really don’t understand all that well yet? For sure. These things don’t really get in the way of creating value for customers, though.&lt;/p&gt;
&lt;p&gt;Your Mileage May Vary.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Behaviour of background goroutines in AWS Lambda</title>
      <link>https://geoffbaskwill.ca/posts/background-goroutines-in-lambda/</link>
      <pubDate>Mon, 02 Nov 2020 00:00:00 +0000</pubDate>
      
      <guid>https://geoffbaskwill.ca/posts/background-goroutines-in-lambda/</guid>
      <description>&lt;p&gt;I was curious what would happen with a &lt;code&gt;time.Ticker&lt;/code&gt; running in an AWS Lambda function.&lt;/p&gt;
&lt;p&gt;It was pretty obvious that the ticker wouldn’t tick while the container was hibernating, but what about when it woke up? Would a bunch of ticks happen if the container had been hibernating for a long time? Would you get a tick at all?&lt;/p&gt;
&lt;h2&gt;tl;dr&lt;/h2&gt;&lt;p&gt;It looks like you get one tick when the function comes out of hibernation (assuming the ticker duration has passed at least once), and if the function never hibernates the ticks happen on time, which for my purposes is pretty much perfect.&lt;/p&gt;
&lt;h2&gt;The code&lt;/h2&gt;&lt;p&gt;I set up a small AWS Lambda function that responds to API Gateway requests and has a goroutine running with a &lt;code&gt;time.Ticker&lt;/code&gt; that ticks every minute:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;package main

import (
  &amp;#34;context&amp;#34;
  &amp;#34;fmt&amp;#34;
  &amp;#34;net/http&amp;#34;
  &amp;#34;sync&amp;#34;
  &amp;#34;time&amp;#34;

  &amp;#34;github.com/aws/aws-lambda-go/events&amp;#34;
  &amp;#34;github.com/aws/aws-lambda-go/lambda&amp;#34;
)

func main() {
  wg := &amp;amp;sync.WaitGroup{}

  ticker := time.NewTicker(time.Second * 60)
  go func() {
    for t := range ticker.C {
      // let the WaitGroup know that we&amp;#39;re working
      wg.Add(1)

      // tell the observer that the ticker actually ticked
      fmt.Println(&amp;#34;tick at&amp;#34;, t)
      
      // simulate a background process that takes a bit to complete
      time.Sleep(time.Second)
      
      // let the WaitGroup know that we&amp;#39;re done
      wg.Done()
    }
  }()

  lambda.Start(func(ctx context.Context, req events.APIGatewayProxyRequest)(events.APIGatewayProxyResponse, error) {
    resp, err := realHandler(ctx, req)
    
    // If the ticker is running, wait for it.
    wg.Wait()

    return resp, err
  })
}

func realHandler(ctx context.Context, req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
  return events.APIGatewayProxyResponse{
    StatusCode: http.StatusPaymentRequired,
  }, nil
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You’ll see how I’ve split out the real handler and the ticker-waiting “middleware” &amp;hellip; this keeps the handler logic separated from the bit that waits for the background goroutine to complete what it’s doing before returning.&lt;/p&gt;
&lt;h2&gt;The test&lt;/h2&gt;&lt;p&gt;I called the function a couple of times, waited a few minutes, and called the function again. The logs told me what happened:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;2020-11-02T14:11:51.061-05:00 START RequestId: f2604bb1-8bc2-445a-b7b2-3893d8d3416d Version: $LATEST
2020-11-02T14:11:51.063-05:00 END RequestId: f2604bb1-8bc2-445a-b7b2-3893d8d3416d
2020-11-02T14:11:51.063-05:00 REPORT RequestId: f2604bb1-8bc2-445a-b7b2-3893d8d3416d Duration: 1.39 ms Billed Duration: 100 ms Memory Size: 1024 MB Max Memory Used: 35 MB Init Duration: 66.79 ms XRAY TraceId: 1-5fa059f6-10e9a1715cb581111721b9a8 SegmentId: 0467a00a5d719145 Sampled: true
&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;2020-11-02T14:11:54.171-05:00 START RequestId: 7a39872e-4b18-42da-b2ff-315a6590a1b6 Version: $LATEST
2020-11-02T14:11:54.174-05:00 END RequestId: 7a39872e-4b18-42da-b2ff-315a6590a1b6
2020-11-02T14:11:54.174-05:00 REPORT RequestId: 7a39872e-4b18-42da-b2ff-315a6590a1b6 Duration: 0.68 ms Billed Duration: 100 ms Memory Size: 1024 MB Max Memory Used: 42 MB XRAY TraceId: 1-5fa059fa-0be52e2845702dd0365eeb74 SegmentId: 5d5f37f527b7de1a Sampled: true
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The first two log blocks show the first two calls, at &lt;code&gt;14:11:51-05:00&lt;/code&gt; and at &lt;code&gt;14:11:54-05:00&lt;/code&gt;. We wouldn’t expect to see a tick log here, and as expected we do not.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;2020-11-02T14:16:28.076-05:00 START RequestId: 488123cd-43bc-4567-9970-00c35bfc91b8 Version: $LATEST
2020-11-02T14:16:28.076-05:00 tick at 2020-11-02 19:16:28.076072523 +0000 UTC m=+277.052607202
2020-11-02T14:16:28.078-05:00 END RequestId: 488123cd-43bc-4567-9970-00c35bfc91b8
2020-11-02T14:16:28.078-05:00 REPORT RequestId: 488123cd-43bc-4567-9970-00c35bfc91b8 Duration: 0.59 ms Billed Duration: 100 ms Memory Size: 1024 MB Max Memory Used: 42 MB XRAY TraceId: 1-5fa05b0c-35afecef72dc3fb25cf4eeef SegmentId: 045243422ccaea72 Sampled: true
&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;2020-11-02T14:20:15.133-05:00 START RequestId: 2dc415ef-f53f-4e35-865d-21b89cd9147e Version: $LATEST
2020-11-02T14:20:15.133-05:00 tick at 2020-11-02 19:20:15.133194003 +0000 UTC m=+504.107026404
2020-11-02T14:20:15.137-05:00 END RequestId: 2dc415ef-f53f-4e35-865d-21b89cd9147e
2020-11-02T14:20:15.137-05:00 REPORT RequestId: 2dc415ef-f53f-4e35-865d-21b89cd9147e Duration: 0.62 ms Billed Duration: 100 ms Memory Size: 1024 MB Max Memory Used: 43 MB XRAY TraceId: 1-5fa05bef-5e8453ea22ff3fa4454e0af6 SegmentId: 183982d42c0b3848 Sampled: true
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The next two log blocks show calls at &lt;code&gt;14:16:28-05:00&lt;/code&gt; and &lt;code&gt;14:20:15-05:00&lt;/code&gt; and one tick happening each time the code is invoked. This would seem to indicate that even if multiple ticks would normally have happened in the time period, they are consolidated into one.&lt;/p&gt;
&lt;p&gt;Neat!&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>
