<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Micah Walter]]></title><description><![CDATA[I write about how I rebooted my career, rewired my brain, and found happiness in suburbia. | Solutions Architecture @ AWS | Things my 3yo said.]]></description><link>https://www.micahwalter.com/</link><image><url>https://www.micahwalter.com/favicon.png</url><title>Micah Walter</title><link>https://www.micahwalter.com/</link></image><generator>Ghost 5.79</generator><lastBuildDate>Fri, 23 Feb 2024 01:25:10 GMT</lastBuildDate><atom:link href="https://www.micahwalter.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[S1 E2 - Building Stuff on AWS in my Basement - API Gateway, AWS Lambda, and Amazon Bedrock]]></title><description><![CDATA[This week, we will go over deploying our generative service to AWS, adding the ability to pass unique identifiers as parameters.]]></description><link>https://www.micahwalter.com/s1-e2-building-stuff-on-aws-in-my-basement/</link><guid isPermaLink="false">65cac2c53a8cfa0001faa2a5</guid><category><![CDATA[Updates]]></category><category><![CDATA[Live]]></category><category><![CDATA[Go]]></category><category><![CDATA[AWS]]></category><category><![CDATA[Amazon Bedrock]]></category><category><![CDATA[CloudFront]]></category><category><![CDATA[DynamoDB]]></category><category><![CDATA[Serverless]]></category><dc:creator><![CDATA[Micah Walter]]></dc:creator><pubDate>Tue, 13 Feb 2024 01:33:45 GMT</pubDate><content:encoded><![CDATA[<p>I have to say, I&apos;m impressed with myself. I managed to pull off another livestream this past Friday. Another 90 minutes of me, slowly walking you through building a generative service on AWS. It was fun, and I even decided to make custom thumbnails like the one below. They need a little work, but one thing at a time.</p><figure class="kg-card kg-embed-card"><iframe width="200" height="113" src="https://www.youtube.com/embed/H3g4yHwS3xE?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen title="Building Stuff on AWS in my Basement   S1 E2   API Gateway  Lambda and Amazon Bedrock"></iframe></figure><p>I can feel the show beginning to turn into a lengthy course in building with Go on AWS. It&apos;s what I had imagined from the start, yet a little slower and highly detailed. This last one, I actually felt a little pressure toward the end to finish up what I wanted to cover within 90 minutes. I didn&apos;t quite make it, so this Friday I intend to get back on the livestream horse and pick up where we left off.</p><p>This week, we will go over deploying our generative service to AWS, adding the ability to pass unique identifiers as parameters. We will also discuss performance and cost concerns, and try and tackle some of those issues by picking from a number of common strategies. We will get a little taste of <a href="https://aws.amazon.com/dynamodb/?ref=micahwalter.com" rel="noreferrer">Amazon DynamoDB</a> and <a href="https://aws.amazon.com/cloudfront/?ref=micahwalter.com" rel="noreferrer">Amazon CloudFront</a> as well. It should be a h00t!</p><p>I also made a few minor technical changes to the stream. 1. I switched to using <a href="https://streamyard.com/?ref=micahwalter.com" rel="noreferrer">StreamYard</a> instead of OBS. It seems much simpler and more powerful. 2. I am going to start &quot;multi-casting&quot; this Friday and will do the live stream on both Twitch  and YouTube at the same time. I realized that Twitch only lets me save shows for 7 days before they are deleted, and YouTube seems like a more natural fit for the content. So, I guess I&apos;m a YouTuber now! You&apos;ll still be able to watch on Twitch if that&apos;s your thing, but al the archives will be on <a href="https://www.youtube.com/@micahaws?ref=micahwalter.com" rel="noreferrer">YouTube</a>.</p><p>Related links:</p><ul><li>Notes from the show - <a href="https://notes.micahwalter.com/Live+Stream+Notes/2024-02-09+Live+Stream+Notes?ref=micahwalter.com">https://notes.micahwalter.com/Live+Stream+Notes/2024-02-09+Live+Stream+Notes</a></li><li>YouTube Channel and Archive - <a href="https://www.youtube.com/@micahaws?ref=micahwalter.com">https://www.youtube.com/@micahaws</a></li><li>Twitch.tv Channel - <a href="https://www.twitch.tv/micahwalter?ref=micahwalter.com">https://www.twitch.tv/micahwalter</a></li></ul><p>I hope to see you this Friday at 3pm ET !!!</p><p>-m</p>]]></content:encoded></item><item><title><![CDATA[S1 E1 - Building Stuff on AWS in my Basement]]></title><description><![CDATA[For my next show, coming up this Friday at 3pm ET, you can expect to hang out with me as I wind my way through building a simple generative service using Go and AWS Lambda.]]></description><link>https://www.micahwalter.com/s1-e1-building-stuff-on-aws-in-my-basement/</link><guid isPermaLink="false">65c1084b780a1400018c8afd</guid><category><![CDATA[Updates]]></category><category><![CDATA[Live]]></category><category><![CDATA[Amazon Bedrock]]></category><category><![CDATA[AWS]]></category><category><![CDATA[Go]]></category><category><![CDATA[Lambda]]></category><category><![CDATA[Serverless]]></category><dc:creator><![CDATA[Micah Walter]]></dc:creator><pubDate>Mon, 05 Feb 2024 18:54:10 GMT</pubDate><content:encoded><![CDATA[<p>I really enjoyed live streaming for the first time last Friday. It was a h00t! If you weren&apos;t able to join live, please check out the recording below. It&apos;s long and slow and that is on purpose.</p><figure class="kg-card kg-embed-card"><iframe width="200" height="113" src="https://www.youtube.com/embed/1L1KDe4yPcs?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen title="Building Stuff on AWS in my Basement | S1 E1 | Hello, Go on Lambda"></iframe></figure><p>Live streaming was fun, however I hit a few glitches this first time around. Toward the start, I noticed that I wasn&apos;t showing anything on my desktop besides the wallpaper. I had thought I was giving you all a tour of a website, but alas, it was just me talking as if I were and you looking at my desktop. I was able to figure it out on the fly during the show by adjusting what was going on in <a href="https://obsproject.com/?ref=micahwalter.com" rel="noreferrer">OBS</a>, the software I use to stream. I have almost no clue how OBS works, or what it really does. It seemed pretty simple when I was testing things ahead of the show!</p><p>I&apos;ll get it. These things take time to sort out if you&apos;ve never done it before. The show is intentionally slow paced, and probably not much different than if you were sitting next to me at work, except that you can hear my inner monologue.</p><p>I also really enjoyed getting back to basics with both Go and AWS Lambda. It&apos;s really fun to hear from folks who are brand new to this space, as I often find myself assuming everyone is extremely advanced and knowledgeable. So, I am gonna keep things this way going forward and build up the complexity over time.</p><p>For my next show, coming up this <a href="https://www.twitch.tv/micahwalter/schedule?seriesID=412f8e6f-bfdd-4fd4-b056-9a503d1e2af4&amp;ref=micahwalter.com" rel="noreferrer">Friday at 3pm ET</a>, you can expect to hang out with me as I wind my way through building a simple generative service using Go and AWS Lambda. I&apos;ll be introducing making API calls to external services and using the results to generate some text with <a href="https://aws.amazon.com/bedrock/?ref=micahwalter.com" rel="noreferrer">Amazon Bedrock</a> and <a href="https://www.anthropic.com/?ref=micahwalter.com" rel="noreferrer">Anthropic Claude</a>. It sounds advanced and complicated, but it&apos;s not. We are gonna talk about each line of code and eventually discuss how to improve this basic system for use in the real world.</p><p>If you&apos;d like to tune in, be sure to <a href="https://www.twitch.tv/micahwalter/schedule?seriesID=412f8e6f-bfdd-4fd4-b056-9a503d1e2af4&amp;ref=micahwalter.com" rel="noreferrer">bookmark this page and add it to your calendar</a>! I hope to see you there.</p><p>-m</p><p>Related Links:</p><ul><li>Notes from last week&apos;s show - <a href="https://notes.micahwalter.com/Live+Stream+Notes/2024-02-01+Live+Stream+Notes?ref=micahwalter.com">https://notes.micahwalter.com/Live+Stream+Notes/2024-02-01+Live+Stream+Notes</a></li><li>YouTube Archive of all shows - <a href="https://www.youtube.com/playlist?list=PLU0SYBGuhqL_ivXmuiwdvQmr8FJvRpino&amp;ref=micahwalter.com">https://www.youtube.com/playlist?list=PLU0SYBGuhqL_ivXmuiwdvQmr8FJvRpino</a></li></ul>]]></content:encoded></item><item><title><![CDATA[LIVE this Friday: Building Stuff on AWS in my Basement]]></title><description><![CDATA[<p>I&apos;m gonna be doing a live-stream this Friday on <a href="https://www.twitch.tv/micahwalter/schedule?seriesID=412f8e6f-bfdd-4fd4-b056-9a503d1e2af4&amp;ref=micahwalter.com" rel="noreferrer">Twitch</a>. It will be just myself, sitting at the desk you see in the photo above, talking about building stuff on AWS for about 90 minutes.</p><p>I&apos;ve been thinking of doing something like this for a while.</p>]]></description><link>https://www.micahwalter.com/building-stuff-on-aws-in-my-basement/</link><guid isPermaLink="false">65baa8e0780a1400018c8a74</guid><category><![CDATA[Updates]]></category><category><![CDATA[AWS]]></category><category><![CDATA[Go]]></category><category><![CDATA[Live]]></category><dc:creator><![CDATA[Micah Walter]]></dc:creator><pubDate>Thu, 01 Feb 2024 15:57:26 GMT</pubDate><media:content url="https://www.micahwalter.com/content/images/2024/01/IMG_6672.JPG" medium="image"/><content:encoded><![CDATA[<img src="https://www.micahwalter.com/content/images/2024/01/IMG_6672.JPG" alt="LIVE this Friday: Building Stuff on AWS in my Basement"><p>I&apos;m gonna be doing a live-stream this Friday on <a href="https://www.twitch.tv/micahwalter/schedule?seriesID=412f8e6f-bfdd-4fd4-b056-9a503d1e2af4&amp;ref=micahwalter.com" rel="noreferrer">Twitch</a>. It will be just myself, sitting at the desk you see in the photo above, talking about building stuff on AWS for about 90 minutes.</p><p>I&apos;ve been thinking of doing something like this for a while. Not a podcast, not a radio show, but a broadcast where I work my way through learning something new in front of an audience.</p><p>For this first show, I&apos;m gonna keep it super simple and entry level. We will be discussing Go, the programming language I&apos;ve been trying to learn over this past year, and how to get Go running on AWS Lambda. I will also get into the developer experience for the above and some useful tips and tricks you might not know about!</p><p>This is an experiment! Don&apos;t expect a nicely polished scene with neon rope lights in the background and a fake plant sitting on top of a brand new Ikea Kalax shelf. That&apos;s not this show. I&apos;ll do my best, and improve over time, and if it winds up being fun and useful, I may do it on a regular basis!</p><p>To tune in, mark your calendar for Friday, Feb 2, at 3:00pm ET, or just click <a href="https://www.twitch.tv/micahwalter/schedule?seriesID=412f8e6f-bfdd-4fd4-b056-9a503d1e2af4&amp;ref=micahwalter.com" rel="noreferrer">this link to get a reminder</a>.</p><p>I hope to see you there!</p><p>-m</p><p></p>]]></content:encoded></item><item><title><![CDATA[Add Fathom Analytics to your Obsidian Publish site]]></title><description><![CDATA[<p>Today I figured out how to embed the tracking code for <a href="https://usefathom.com/?ref=micahwalter.com" rel="noreferrer">Fathom Analytics</a> into an <a href="https://obsidian.md/publish?ref=micahwalter.com" rel="noreferrer">Obsidian Publish</a> website. It&apos;s easy.</p><ol><li>Create a file in the root of your Obsidian Vault called <code>publish.js</code> - You&apos;ll need to use an editor like VS Code for this as</li></ol>]]></description><link>https://www.micahwalter.com/add-fathom-analytics-to-your-obsidian-publish-site/</link><guid isPermaLink="false">65b68f42a2916100013eeea4</guid><category><![CDATA[TIL]]></category><category><![CDATA[Websites]]></category><category><![CDATA[Analytics]]></category><dc:creator><![CDATA[Micah Walter]]></dc:creator><pubDate>Sun, 28 Jan 2024 17:35:51 GMT</pubDate><content:encoded><![CDATA[<p>Today I figured out how to embed the tracking code for <a href="https://usefathom.com/?ref=micahwalter.com" rel="noreferrer">Fathom Analytics</a> into an <a href="https://obsidian.md/publish?ref=micahwalter.com" rel="noreferrer">Obsidian Publish</a> website. It&apos;s easy.</p><ol><li>Create a file in the root of your Obsidian Vault called <code>publish.js</code> - You&apos;ll need to use an editor like VS Code for this as Obsidian won&apos;t handle it.</li><li>Add this code to that file, replacing <code>&lt;your-site-code&gt;</code> with your actual site code.</li></ol>
<!--kg-card-begin: html-->
<script src="https://gist.github.com/micahwalter/517cfb56eb8d032a58c96bf214c332fd.js"></script>
<!--kg-card-end: html-->
<ol start="3"><li>Use Obsidian to publish the <code>publish.js</code> file just like any other file.</li></ol><p>That&apos;s it!</p>]]></content:encoded></item><item><title><![CDATA[Trigger builds in AWS Amplify with DynamoDB]]></title><description><![CDATA[<p>I&apos;m building a thing. I&apos;ll write more about that thing in the near future. But, in the meantime, I thought I&apos;d write a little about one small other thing I learned along the way.</p><p>The thing I am building has two main components.</p><ol><li>A</li></ol>]]></description><link>https://www.micahwalter.com/trigger-builds-in-aws-amplify-with-dynamodb/</link><guid isPermaLink="false">6596f52ff56aa10001973e16</guid><category><![CDATA[TIL]]></category><category><![CDATA[AWS]]></category><category><![CDATA[DynamoDB]]></category><category><![CDATA[Lambda]]></category><category><![CDATA[SAM]]></category><category><![CDATA[Amplify]]></category><dc:creator><![CDATA[Micah Walter]]></dc:creator><pubDate>Thu, 04 Jan 2024 18:36:41 GMT</pubDate><media:content url="https://www.micahwalter.com/content/images/2024/01/IMG_6680.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://www.micahwalter.com/content/images/2024/01/IMG_6680.jpg" alt="Trigger builds in AWS Amplify with DynamoDB"><p>I&apos;m building a thing. I&apos;ll write more about that thing in the near future. But, in the meantime, I thought I&apos;d write a little about one small other thing I learned along the way.</p><p>The thing I am building has two main components.</p><ol><li>A back-end workflow that uses <a href="https://aws.amazon.com/step-functions/?ref=micahwalter.com" rel="noreferrer">AWS Step Functions</a> to periodically orchestrate fetching and processing some data before storing it in an <a href="https://aws.amazon.com/dynamodb/?ref=micahwalter.com" rel="noreferrer">Amazon DynamoDB</a> table.</li><li>A front-end website built using <a href="https://nextjs.org/?ref=micahwalter.com" rel="noreferrer">Next.js</a> that displays the data as a static website, hosted on <a href="https://aws.amazon.com/amplify/?ref=micahwalter.com" rel="noreferrer">AWS Amplify</a>.</li></ol><p>The front-end needs to be rebuilt whenever there is new data to display. With AWS Amplify, you can easily create a <a href="https://docs.aws.amazon.com/amplify/latest/userguide/webhooks.html?ref=micahwalter.com" rel="noreferrer">Webhook</a> to invoke a new build. Here&apos;s how it works.</p><p>In my SAM template, I configure DynamoDB streams like this:</p>
<!--kg-card-begin: html-->
<script src="https://gist.github.com/micahwalter/f1b7e9da822117de832ab7dc93fc3554.js"></script>
<!--kg-card-end: html-->
<p>Then I need an AWS Lambda function to trigger off the DynamoDB stream. It&apos;s defined in my SAM template like this:</p>
<!--kg-card-begin: html-->
<script src="https://gist.github.com/micahwalter/eb59a7e7678ef84761f48b10804469ce.js"></script>
<!--kg-card-end: html-->
<p>The function code itself is super simple. It just makes a POST request to the Webhook.</p>
<!--kg-card-begin: html-->
<script src="https://gist.github.com/micahwalter/7b5e026e3f2fd2bcbebf902937aef8ed.js"></script>
<!--kg-card-end: html-->
<p>There is one little trick I am doing here you may have noticed. I am storing the Amplify Webhook URL in <a href="https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html?ref=micahwalter.com" rel="noreferrer">AWS Systems Manager Parameter Store</a> and setting it as an environmental variable in my Lambda function. This way I don&apos;t have to hard-code anything into my SAM template.</p><p><code>AMPLIFY_WEBHOOK_URL: &apos;{{resolve:ssm:/new-thing/amplify-webhook-url:1}}&apos;</code></p><p>Now, whenever my State Machine runs, it updates DynamoDB, which triggers a Lambda, which tells Amplify to rebuild the site. Yay!</p>]]></content:encoded></item><item><title><![CDATA[Dealing with AWS Lambda deployment package size limits]]></title><description><![CDATA[<p>I had an interesting conversation at work today around package size limits for AWS Lambda and it got me thinking about a number of strategies for dealing with these limits.</p><h3 id="the-limits">The limits</h3><p>First, here are the limits. As per the <a href="https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html?ref=micahwalter.com" rel="noreferrer">documentation</a>, your Lambda function, including all its source code, layers,</p>]]></description><link>https://www.micahwalter.com/lambda-package-size-limits/</link><guid isPermaLink="false">65947266f56aa10001973d78</guid><category><![CDATA[TIL]]></category><category><![CDATA[Lambda]]></category><dc:creator><![CDATA[Micah Walter]]></dc:creator><pubDate>Wed, 03 Jan 2024 02:55:57 GMT</pubDate><media:content url="https://www.micahwalter.com/content/images/2024/01/IMG_4128.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://www.micahwalter.com/content/images/2024/01/IMG_4128.jpg" alt="Dealing with AWS Lambda deployment package size limits"><p>I had an interesting conversation at work today around package size limits for AWS Lambda and it got me thinking about a number of strategies for dealing with these limits.</p><h3 id="the-limits">The limits</h3><p>First, here are the limits. As per the <a href="https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html?ref=micahwalter.com" rel="noreferrer">documentation</a>, your Lambda function, including all its source code, layers, and any custom runtime must fit within the size limits listed below:</p><ul><li>In the AWS Console Editor - 3MB</li><li>Zipped for direct upload - 50MB</li><li>Unzipped (using an S3 bucket) - 250MB</li><li>Container image - 10GB</li></ul><h3 id="how-to-deal-with-the-limits">How to deal with the limits</h3><p>Here&apos;s a few ideas I came up with on how to deal with these limitations.</p><ol><li>First, optimize the code as much as possible to shrink the dependency size and make sure you aren&apos;t importing unnecessary libraries. You can do this by <a href="https://avilpage.com/2020/02/reduce-python-package-footprint.html?ref=micahwalter.com" rel="noreferrer">building dependencies from source</a>, and by making sure you are only importing the parts of the library you actually need vs. a global import.</li><li>Consider splitting the lambda into separate steps and use <a href="https://aws.amazon.com/step-functions/?ref=micahwalter.com" rel="noreferrer">AWS Step Functions</a> to orchestrate. For example, a Lambda that fetches data from MySQL using <a href="https://pypi.org/project/pymysql/?ref=micahwalter.com" rel="noreferrer">PyMySQL</a>, and then another Lambda that processes that data using <a href="https://pypi.org/project/pandas/?ref=micahwalter.com" rel="noreferrer">Pandas</a> would mean your package size could be split across two separate functions, where each function only loads the libraries required.</li><li>Use a container - This will up the size limit to 10GB from 250MB. That&apos;s a big difference!</li><li>Use <a href="https://aws.amazon.com/efs/?ref=micahwalter.com" rel="noreferrer">Amazon Elastic File System</a> (EFS) - You will need a VPC and an EC2 instance to write the initial data to the EFS volume, but <a href="https://towardsdatascience.com/deploying-large-packages-on-aws-lambda-using-efs-3a707f83d918?ref=micahwalter.com" rel="noreferrer">this configuration</a> can give your Lambda plenty of room to breathe.</li></ol>]]></content:encoded></item><item><title><![CDATA[Deploying Serverless Go projects with AWS SAM Pipelines and GitHub Actions]]></title><description><![CDATA[<p>Wow, that title is a mouthful. Here&apos;s what it means:</p><ul><li>You can use <a href="https://aws.amazon.com/serverless/sam/?ref=micahwalter.com" rel="noreferrer">AWS SAM</a> to easily construct at Serverless Application on AWS where the <a href="https://aws.amazon.com/lambda?ref=micahwalter.com" rel="noreferrer">AWS Lambda</a> code is written in Go</li><li>You can deploy your app to AWS from the CLI with <code>sam deploy</code> which is nice</li></ul>]]></description><link>https://www.micahwalter.com/deploying-serverless-go-projects-with-aws-sam-pipelines-and-github-actions/</link><guid isPermaLink="false">654a9c64cef11b0001787d02</guid><category><![CDATA[TIL]]></category><category><![CDATA[AWS]]></category><category><![CDATA[Go]]></category><category><![CDATA[SAM]]></category><category><![CDATA[CICD]]></category><dc:creator><![CDATA[Micah Walter]]></dc:creator><pubDate>Tue, 07 Nov 2023 20:54:51 GMT</pubDate><media:content url="https://www.micahwalter.com/content/images/2023/11/20230421_0008.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://www.micahwalter.com/content/images/2023/11/20230421_0008.jpg" alt="Deploying Serverless Go projects with AWS SAM Pipelines and GitHub Actions"><p>Wow, that title is a mouthful. Here&apos;s what it means:</p><ul><li>You can use <a href="https://aws.amazon.com/serverless/sam/?ref=micahwalter.com" rel="noreferrer">AWS SAM</a> to easily construct at Serverless Application on AWS where the <a href="https://aws.amazon.com/lambda?ref=micahwalter.com" rel="noreferrer">AWS Lambda</a> code is written in Go</li><li>You can deploy your app to AWS from the CLI with <code>sam deploy</code> which is nice when you are building something on your own, or just getting started</li><li>Once your project grows and begins to involve others, you will likely want to incorporate some kind of CI/CD pipeline</li><li><a href="https://aws.amazon.com/blogs/compute/introducing-aws-sam-pipelines-automatically-generate-deployment-pipelines-for-serverless-applications/?ref=micahwalter.com" rel="noreferrer">AWS SAM Pipelines</a> and <a href="https://github.com/features/actions?ref=micahwalter.com" rel="noreferrer">GitHub Actions</a> make this all work really nicely!</li><li>These are my notes so far</li></ul><p>An AWS SAM Pipeline consists of two major components:</p><ol><li>The <em>bootstrap command</em> - This command ( <code>sam pipeline bootstrap</code>) needs to be done for each stage in your pipeline (test, prod, etc.). The end result is a handful of resources deployed in your AWS account that will be required by the pipeline itself. These are things like Roles, Policies and an Amazon S3 Bucket.</li><li>The <em>init command</em> - This command ( <code>sam pipeline init</code> ) will walk you through a little wizard to help craft a GitHub Action template. This file will appear in your repository at <code>.github/workflows/pipeline.yml</code> and contains all the configuration GitHub Actions will need to build, test and deploy your application whenever you push new changes to GitHub.</li></ol><p>For my project I chose to use GitHub Actions for my CI/CD tooling, but you can choose from a number of other popular tools like Jenkins, GitLab or AWS CodePipeline. I really like GitHub Actions.</p><p>One thing I noticed was that the <code>pipeline.yml</code> file contained a number of fields that included my AWS account number and a few ARNs. In a private/corporate repository, this might be fine, but for my public repo, I chose to change these to use GitHub&apos;s repository variables. Here&apos;s what my final list of fields looked like:</p>
<!--kg-card-begin: html-->
<script src="https://gist.github.com/micahwalter/4753caacdf58db5f70eff037f1079dbe.js"></script>
<!--kg-card-end: html-->
<p>Once you set these up, you just need to create the actual variables in the GitHub settings page for your repo.</p><p>Another issue I ran into was building a Go program with GitHub Actions wasn&apos;t working right out of the box. When I do a <code>sam build</code> and <code>sam deploy</code> from the command line, everything works just fine, but that&apos;s because I am building with the installation of Go on my laptop. On GitHub, it will need to have Go installed as part of the build process. The template I started with didn&apos;t know about this, so I had to modify it to look like this:</p>
<!--kg-card-begin: html-->
<script src="https://gist.github.com/micahwalter/b43ad516374b3e1a2a25b3dd413ee5c5.js"></script>
<!--kg-card-end: html-->
<p>You can see here that instead of just doing <code>sam build</code> I first need to install Go and add it to the <code>$PATH</code>. </p><p>Once I made these changes and made sure all my variables and secrets were setup in the repo settings, I was able to push my code and watch it deploy to AWS.</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.micahwalter.com/content/images/2023/11/Screenshot-2023-11-07-at-11.21.11-AM.png" class="kg-image" alt="Deploying Serverless Go projects with AWS SAM Pipelines and GitHub Actions" loading="lazy" width="2000" height="683" srcset="https://www.micahwalter.com/content/images/size/w600/2023/11/Screenshot-2023-11-07-at-11.21.11-AM.png 600w, https://www.micahwalter.com/content/images/size/w1000/2023/11/Screenshot-2023-11-07-at-11.21.11-AM.png 1000w, https://www.micahwalter.com/content/images/size/w1600/2023/11/Screenshot-2023-11-07-at-11.21.11-AM.png 1600w, https://www.micahwalter.com/content/images/2023/11/Screenshot-2023-11-07-at-11.21.11-AM.png 2126w" sizes="(min-width: 1200px) 1200px"></figure><p>This pipeline has a couple interesting ... features:</p><ol><li>You can use feature branches like <code>feature-new-gizmo</code> to deploy from a separate feature branch. It will also clean these up as you delete old feature branches.</li><li>It has two stages for &quot;testing&quot; and &quot;production.&quot; In this current setup, it will just deploy both of them on every new push to <code>main</code>. But, you can utilize GitHub Environments to add a manual intervention or approval step for the production branch.</li></ol><p>Here&apos;s my <a href="https://github.com/go-micah/go-sam-pipes?ref=micahwalter.com" rel="noreferrer">demo application</a> on GitHub including the SAM Pipeline.</p><p>That&apos;s it!</p>]]></content:encoded></item><item><title><![CDATA[A SAM Starter Template for Serverless Go Projects on AWS]]></title><description><![CDATA[<p>A while back I created a repo on GitHub that was simply the output of doing <code>sam init</code> and choosing the AWS Quick Start Template for a Hello World Example.</p><p>From there, I simplified the <a href="https://aws.amazon.com/serverless/sam/?ref=micahwalter.com" rel="noreferrer">SAM</a> <code>template.yml</code> file a little, restructured the folder where all my Go code lives,</p>]]></description><link>https://www.micahwalter.com/a-sam-starter-template-for-serverless-go-projects/</link><guid isPermaLink="false">654963b264fb5600014de993</guid><category><![CDATA[TIL]]></category><category><![CDATA[AWS]]></category><category><![CDATA[SAM]]></category><category><![CDATA[Serverless]]></category><category><![CDATA[Go]]></category><dc:creator><![CDATA[Micah Walter]]></dc:creator><pubDate>Mon, 06 Nov 2023 22:17:17 GMT</pubDate><media:content url="https://www.micahwalter.com/content/images/2023/11/IMG_5652.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://www.micahwalter.com/content/images/2023/11/IMG_5652.jpg" alt="A SAM Starter Template for Serverless Go Projects on AWS"><p>A while back I created a repo on GitHub that was simply the output of doing <code>sam init</code> and choosing the AWS Quick Start Template for a Hello World Example.</p><p>From there, I simplified the <a href="https://aws.amazon.com/serverless/sam/?ref=micahwalter.com" rel="noreferrer">SAM</a> <code>template.yml</code> file a little, restructured the folder where all my Go code lives, and added a <code>.devcontainer</code> file to help with getting things working on GitHub Codespaces.</p><p>To start a new project locally, all you need to do is the following:</p><pre><code>&gt; mkdir your-project
&gt; cd your-project
&gt; sam init</code></pre><p>From here, choose option 2 &quot;Custom Template Location&quot; and enter the repository URL &#x2013; <a href="https://github.com/go-micah/go-serverless-sam-template?ref=micahwalter.com">https://github.com/go-micah/go-serverless-sam-template</a></p><figure class="kg-card kg-image-card"><img src="https://www.micahwalter.com/content/images/2023/11/Screenshot-2023-11-06-at-5.04.40-PM.png" class="kg-image" alt="A SAM Starter Template for Serverless Go Projects on AWS" loading="lazy" width="1598" height="448" srcset="https://www.micahwalter.com/content/images/size/w600/2023/11/Screenshot-2023-11-06-at-5.04.40-PM.png 600w, https://www.micahwalter.com/content/images/size/w1000/2023/11/Screenshot-2023-11-06-at-5.04.40-PM.png 1000w, https://www.micahwalter.com/content/images/2023/11/Screenshot-2023-11-06-at-5.04.40-PM.png 1598w" sizes="(min-width: 720px) 720px"></figure><p>All this does is it downloads the files to your local machine, without cloning the repo, to be used as a starting point for a new project. </p><p>Did you know you can easily create your own templates for AWS SAM? Nice!</p>]]></content:encoded></item><item><title><![CDATA[Working with Amazon Bedrock's Streaming Response API and Go]]></title><description><![CDATA[<p>While working on my <a href="https://www.micahwalter.com/building-a-generative-ai-cli-with-amazon-bedrock-and-go/" rel="noreferrer">chat-cli</a> program, I realized that waiting for a response from <a href="https://aws.amazon.com/bedrock?ref=micahwalter.com" rel="noreferrer">Amazon Bedrock</a> could take some time, depending on the nature of your prompt. To offer a better user experience, I looked into the <code>InvokeModelWithResponseStream</code> API method, which allows you to receive the response from Bedrock in</p>]]></description><link>https://www.micahwalter.com/working-with-amazon-bedrocks-streaming-response-api-and-go/</link><guid isPermaLink="false">65452b3e64fb5600014de947</guid><category><![CDATA[TIL]]></category><category><![CDATA[Go]]></category><category><![CDATA[AI]]></category><category><![CDATA[Amazon Bedrock]]></category><category><![CDATA[GenerativeAI]]></category><category><![CDATA[Chat-CLI]]></category><dc:creator><![CDATA[Micah Walter]]></dc:creator><pubDate>Fri, 03 Nov 2023 17:39:50 GMT</pubDate><media:content url="https://www.micahwalter.com/content/images/2023/11/IMG_5655.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://www.micahwalter.com/content/images/2023/11/IMG_5655.jpg" alt="Working with Amazon Bedrock&apos;s Streaming Response API and Go"><p>While working on my <a href="https://www.micahwalter.com/building-a-generative-ai-cli-with-amazon-bedrock-and-go/" rel="noreferrer">chat-cli</a> program, I realized that waiting for a response from <a href="https://aws.amazon.com/bedrock?ref=micahwalter.com" rel="noreferrer">Amazon Bedrock</a> could take some time, depending on the nature of your prompt. To offer a better user experience, I looked into the <code>InvokeModelWithResponseStream</code> API method, which allows you to receive the response from Bedrock in chunks rather than all at once. This means you can begin to print out the response to the user as it arrives instead of just showing some equivalent of a spinning beach ball.</p><p>The problem was, I didn&apos;t really understand how to deal with the <code>InvokeModelWithResponseStream</code> in Go. I looked through the documentation and eventually figured out that it was leveraging Go&apos;s Channels feature, which I also didn&apos;t know much about.</p><p>It turns out that Go Channels, and Go Routines are pretty powerful and somewhat simple once you understand what&apos;s going on under the hood. I found a nice tutorial <a href="https://gobyexample.com/goroutines?ref=micahwalter.com" rel="noreferrer">here</a>, and <a href="https://gobyexample.com/channels?ref=micahwalter.com" rel="noreferrer">here</a>, and created my own playground to test things out on my own.</p>
<!--kg-card-begin: html-->
<script src="https://gist.github.com/micahwalter/ca87a494902f84990b8898fe6b82db90.js"></script>
<!--kg-card-end: html-->
<p>The way I understand this, Go Routines allow you to launch multiple non-blocking threads. This is nice, but it can be difficult to manage taking action on any of these threads when they are complete. To deal with that issue, there are Go Channels, which allow you to essentially send messages from one Go Routine to another.</p><p>In my sample code above, I am trying a few different approaches to calling a long running process. The first is a standard function call. Everything has to wait 10 seconds until that function is complete. The second is a started in a Go Routine, using the <code>go</code> syntax. This process is non-blocking, but if the program completes before this routine is done, we may not see its output. The third and fourth are Go Routines with a Go Channel. These allow us to launch non-blocking threads and send some output back to the main function once they are done.</p><p>For Bedrock&apos;s <code>InvokeModelWithResponseStream</code> API method it works pretty much the same.</p><p>First, you make the API call like this:</p>
<!--kg-card-begin: html-->
<script src="https://gist.github.com/micahwalter/7e63e9dbbf8c3511eb3ff5f366c9097b.js"></script>
<!--kg-card-end: html-->
<p>The response from this call will open a Go Channel, which you can react to in a loop like this:</p>
<!--kg-card-begin: html-->
<script src="https://gist.github.com/micahwalter/8e0562ad9deb35ab410c36fe9c2f1a48.js"></script>
<!--kg-card-end: html-->
<p>In this code, we grab the Go Channel with <code>stream.Events()</code> and then in the loop we are capturing each event with the Go Channel syntax <code>event := &lt;- events</code>. From here we are just testing to see if we have any new events before breaking out of the loop and closing the stream. If we have new events, we print them as they arrive. This winds up looking like a streaming response to the user, and is much better than waiting for the entire response to arrive!</p>]]></content:encoded></item><item><title><![CDATA[A super simple TTY loop in Go]]></title><description><![CDATA[<p>In <a href="https://www.micahwalter.com/building-a-generative-ai-cli-with-amazon-bedrock-and-go/" rel="noreferrer">yesterday&apos;s post</a> I talked about building an <a href="https://aws.amazon.com/bedrock?ref=micahwalter.com" rel="noreferrer">Amazon Bedrock</a> powered CLI that allowed for an interactive chat. Below is more or less the code I started with to create the command line chat.</p>
<!--kg-card-begin: html-->
<script src="https://gist.github.com/micahwalter/a2c2c3d3f8713747c18bf0f01e924db8.js"></script>
<!--kg-card-end: html-->
<p>As you can see, there is an infinite loop nested within another infinite loop.</p>]]></description><link>https://www.micahwalter.com/a-super-simple-tty-interface-in-go/</link><guid isPermaLink="false">6543edee64fb5600014de916</guid><category><![CDATA[TIL]]></category><category><![CDATA[Go]]></category><category><![CDATA[Amazon Bedrock]]></category><category><![CDATA[Chat-CLI]]></category><dc:creator><![CDATA[Micah Walter]]></dc:creator><pubDate>Thu, 02 Nov 2023 18:53:22 GMT</pubDate><media:content url="https://www.micahwalter.com/content/images/2023/11/IMG_5403.JPG" medium="image"/><content:encoded><![CDATA[<img src="https://www.micahwalter.com/content/images/2023/11/IMG_5403.JPG" alt="A super simple TTY loop in Go"><p>In <a href="https://www.micahwalter.com/building-a-generative-ai-cli-with-amazon-bedrock-and-go/" rel="noreferrer">yesterday&apos;s post</a> I talked about building an <a href="https://aws.amazon.com/bedrock?ref=micahwalter.com" rel="noreferrer">Amazon Bedrock</a> powered CLI that allowed for an interactive chat. Below is more or less the code I started with to create the command line chat.</p>
<!--kg-card-begin: html-->
<script src="https://gist.github.com/micahwalter/a2c2c3d3f8713747c18bf0f01e924db8.js"></script>
<!--kg-card-end: html-->
<p>As you can see, there is an infinite loop nested within another infinite loop. One of my favorite aspects of Go is the <code>for</code> loop, which is the only kind of loop and used to create any kind of other loop. Loops!</p><p>The main function kicks off the first infinite <code>for</code> loop. This calls the <code>stringPrompt</code> function which starts the second infinite loop to capture input via <code>stdin</code> and waits for the user to press a <code>\n</code>. Then it returns the captured <code>string</code> to <code>main</code> which prints it out for demo purposes before it starts all over again.</p>]]></content:encoded></item><item><title><![CDATA[Building a Generative AI CLI with Amazon Bedrock and Go]]></title><description><![CDATA[<p><a href="https://github.com/go-micah/chat-cli?ref=micahwalter.com">chat-cli</a> is a project I&apos;ve been working on for the past couple months. It started out as a way to kick the tires on the now publicly available <a href="https://aws.amazon.com/bedrock/?ref=micahwalter.com">Amazon Bedrock</a> service, and also as a way for me to learn a bit more about Go, and the AWS</p>]]></description><link>https://www.micahwalter.com/building-a-generative-ai-cli-with-amazon-bedrock-and-go/</link><guid isPermaLink="false">654282bda37efc000148b2ca</guid><category><![CDATA[Updates]]></category><category><![CDATA[Projects]]></category><category><![CDATA[Go]]></category><category><![CDATA[AWS]]></category><category><![CDATA[Amazon Bedrock]]></category><category><![CDATA[LLM]]></category><category><![CDATA[GenerativeAI]]></category><category><![CDATA[AI]]></category><category><![CDATA[Chat-CLI]]></category><dc:creator><![CDATA[Micah Walter]]></dc:creator><pubDate>Wed, 01 Nov 2023 20:59:50 GMT</pubDate><media:content url="https://www.micahwalter.com/content/images/2023/11/000052360026.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://www.micahwalter.com/content/images/2023/11/000052360026.jpg" alt="Building a Generative AI CLI with Amazon Bedrock and Go"><p><a href="https://github.com/go-micah/chat-cli?ref=micahwalter.com">chat-cli</a> is a project I&apos;ve been working on for the past couple months. It started out as a way to kick the tires on the now publicly available <a href="https://aws.amazon.com/bedrock/?ref=micahwalter.com">Amazon Bedrock</a> service, and also as a way for me to learn a bit more about Go, and the AWS SDK for Go version 2. Since then, it has turned into a bit of an exploration into command line interface design, which is pretty interesting to me!</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.micahwalter.com/content/images/2023/11/chat-cli-4-1.png" class="kg-image" alt="Building a Generative AI CLI with Amazon Bedrock and Go" loading="lazy" width="2000" height="1397" srcset="https://www.micahwalter.com/content/images/size/w600/2023/11/chat-cli-4-1.png 600w, https://www.micahwalter.com/content/images/size/w1000/2023/11/chat-cli-4-1.png 1000w, https://www.micahwalter.com/content/images/size/w1600/2023/11/chat-cli-4-1.png 1600w, https://www.micahwalter.com/content/images/2023/11/chat-cli-4-1.png 2276w" sizes="(min-width: 1200px) 1200px"></figure><h2 id="a-cli-for-llms-micahs-version">A CLI for LLMs (Micah&apos;s Version)</h2><p>There are plenty of command line interfaces out there for working with large language models (LLMs). I especially like Simon Willison&apos;s <a href="https://llm.datasette.io/?ref=micahwalter.com">llm</a> project, which is built in Python and allows for a nice CLI to work with OpenAI LLMs and more. I drew a lot of inspiration from his project, and tried to create something similar for Amazon Bedrock.</p><p>In case you are unfamiliar, Amazon Bedrock is a new service from AWS that offers customers &quot;<em>The easiest way to build and scale generative AI applications with foundation models.</em>&quot; It provides a unified API to access a growing list of foundation models without having to worry about provisioning infrastructure.</p><p>With Bedrock you can currently access foundation models from the following providers:</p><ol><li>Titan from Amazon - (currently in preview).</li><li>Claude from Anthropic</li><li>Jurassic-2 from AI21 Labs</li><li>Command from Cohere</li><li>Stable Diffusion from Stability AI</li><li>Llama 2 from Meta - (coming soon)</li></ol><p>Each model has different capabilities and nuances, which I&apos;ll describe in more detail below. Except for Stable Diffusion, these are all text based models, which allow you to have contextual conversations, summarize documents, generate new content like blogs or emails, and much, much more. Stable Diffusion allows for image generation from a text prompt.</p><p>Bedrock is a quickly growing service, and I&apos;m keen to explore all its bells and whistles in the future, but for now, a simple command line program sounds like a nice way to get to know the service.</p><h2 id="getting-started">Getting Started</h2><p>Initially my thought was to build a command line program that could talk to Anthropic&apos;s Claude in an interactive chat type of interface. Eventually I realized that what I really wanted was a program that could talk to any of the available models with a variety of interfaces and options.</p><p>To get started, I wrote a simple program in Go that created a chat style interaction at the prompt. The prompt would capture your input, mold it into the style expected by Claude, and send it up to Bedrock via the <a href="https://pkg.go.dev/github.com/aws/aws-sdk-go-v2?ref=micahwalter.com">AWS SDK for Go</a>.</p><p>Creating the chat loop was pretty simple. I wrote a function called <code>stringPrompt</code> that waits for input from the user. This gets called from the main program in an infinite loop, so once you send your prompt and get a response back from Bedrock, you wind up back at the prompt again, waiting for your next input.</p>
<!--kg-card-begin: html-->
<script src="https://gist.github.com/micahwalter/a7d77d1f5aca03b5738787c1f64ecb78.js"></script>
<!--kg-card-end: html-->
<p>Sending a prompt to Bedrock was also pretty trivial. The <code>InvokeModel</code> API method requires a small payload of info related to the model you want to invoke, and the details of your prompt. Within the AWS Console, you can try things out in the Bedrock Playground, which will generate a payload based on the model and settings you&apos;ve chosen.</p>
<!--kg-card-begin: html-->
<script src="https://gist.github.com/micahwalter/454c09c04da028ae0fed9c8727f32bfb.js"></script>
<!--kg-card-end: html-->
<p>To keep things simple, I hard-coded most of the options based on my experience in the Bedrock Playground, and focused on designing the prompt format to look like what Claude was expecting. Claude has the idea of &quot;Stop Words&quot; which are used to give meaning to the conversation you are sending. For example, the default stop word is <code>/n/nHuman:</code> so your prompt needs to include this to separate your prompt from the responses from Claude.</p><p>There are lots of additional options and features for interacting with Claude, which you can <a href="https://www.anthropic.com/index/claude-2-amazon-bedrock?ref=micahwalter.com">read about on their website</a>. I believe this is called &quot;prompt engineering!&quot;</p><h2 id="its-alive">It&apos;s alive!</h2><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.micahwalter.com/content/images/2023/11/chat-cli-1.png" class="kg-image" alt="Building a Generative AI CLI with Amazon Bedrock and Go" loading="lazy" width="1982" height="1548" srcset="https://www.micahwalter.com/content/images/size/w600/2023/11/chat-cli-1.png 600w, https://www.micahwalter.com/content/images/size/w1000/2023/11/chat-cli-1.png 1000w, https://www.micahwalter.com/content/images/size/w1600/2023/11/chat-cli-1.png 1600w, https://www.micahwalter.com/content/images/2023/11/chat-cli-1.png 1982w" sizes="(min-width: 1200px) 1200px"></figure><p>Once I had this all wired up and working, I noticed a couple details.</p><ol><li>Claude (or any model for that matter) only knows about whatever you send it each time. It doesn&apos;t have a persistent memory of your conversation. So while sending &quot;Hi, My name is Micah&quot; might result in &quot;Hi, Micah.&quot; as a response from Claude, it won&apos;t remember that context the next time you send a message, unless you include it in the prompt.</li><li>The <code>InvokeModel</code> API is a synchronous request, which means you might wind up waiting for a good amount of time for a response to arrive, depending on the nature of your prompt.</li></ol><p>To deal with #1 I investigated two different approaches. The first was to simply keep the running conversation in memory, stored as a <code>string</code>. While this could eventually run up against some hardware limits for the user, it likely will work for most conversation sessions. The second approach is to store the conversation transcript to disk and offer a way to load it back into memory. This seemed like a good idea when I started working on it, but in practice, I am unsure if it&apos;s really all that useful. Claude generates responses based on the text you send it, so it really becomes a matter of how much context you need to give it to get the kind of response you&apos;d like to see. Remembering my name so that it can then use my name to generate a poem is nice, but it may not be important to remember every single interaction in the conversation. I&apos;m still struggling to understand how to deal with this issue. Another side effect this brings up is that your conversation transcript will just grow and grow over time, which means you will begin to consume more and more input tokens, which have a limit, depending on which model you are using. This is especially problematic when you begin to want to include documents as part of the context as you need to carefully manage how many copies of the same text are sent to the LLM.</p><p>To deal with #2 I also investigated two different approaches. The simplest, dumbest solution was to add some kind of &quot;wait state&quot; indicator. Think spinning beach ball. For this, I found a nice Go package called &quot;<a href="https://github.com/briandowns/spinner?ref=micahwalter.com">Spinner</a>&quot; which makes it really easy to add some kind of user feedback while you wait for a response. This is nice, but the user is still waiting for a response. The second approach was to implement the <code>InvokeModelWithResponseStream</code> API. This API appeared to do what I wanted by sending the response back in chunks rather than all at once, so that the user begins to see feedback right away. The only issue was it leveraged Go Channels, which was something I wasn&apos;t familiar with. So, I had to learn all about <a href="https://go.dev/tour/concurrency/2?ref=micahwalter.com">Go Channels</a>.</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.micahwalter.com/content/images/2023/11/chat-cli-2.png" class="kg-image" alt="Building a Generative AI CLI with Amazon Bedrock and Go" loading="lazy" width="1982" height="1548" srcset="https://www.micahwalter.com/content/images/size/w600/2023/11/chat-cli-2.png 600w, https://www.micahwalter.com/content/images/size/w1000/2023/11/chat-cli-2.png 1000w, https://www.micahwalter.com/content/images/size/w1600/2023/11/chat-cli-2.png 1600w, https://www.micahwalter.com/content/images/2023/11/chat-cli-2.png 1982w" sizes="(min-width: 1200px) 1200px"></figure><h2 id="evolving-the-project">Evolving the project</h2><p>After getting things more or less working, I decided I wanted to make two major changes to progress the project forward.</p><p>So far my project was nothing more than a single <code>main.go</code> file. I knew I&apos;d need to think a little more critically about the overall design of the software to accommodate the evolution of the project as I continued to experiment and try new things. For this, I turned to the very lovely Go packages <a href="https://cobra.dev/?ref=micahwalter.com">Cobra</a> and <a href="https://github.com/spf13/viper?ref=micahwalter.com">Viper</a>. Cobra is a framework for building CLI tools in Go. It provides all the structure and tooling to set up a CLI program quickly, and allows you to easily add new commands, flags and all sort of options as the program grows over time. Viper is for dealing with configuration. The two packages work hand in hand and together allow me to not have to think too hard about how to build a CLI tool in 2023!</p><p>I spent a few hours re-factoring my project to work with Cobra and Viper and then began designing the overall interface. Through this process I realized a couple of things.</p><ol><li>I wanted to offer multiple commands instead of just a chat program. So far I have created a chat command and a prompt command. The chat command does what I had already done, which is to put the user into an interactive chat session. The prompt command allows to user to simply send a single prompt.</li><li>I also realized that I really wanted to allow users to access any of the LLMs available in Bedrock. Cobra and Viper offered me an easy way to add feature flags, so I set about implementing the rest of the models I had available.</li></ol><h2 id="not-all-llms-are-created-equal">Not all LLMs are created equal</h2><p>While Amazon Bedrock offers a unified API for interacting with LLMs, each LLM has its own unique characteristics. This means that a program that allows a user to interact with multiple LLMs will need to take these unique characteristics into account. For example, not all LLMs are capable of sending a streaming response. As well, each LLM has its own levers you can pull to adjust parameters like Temperature, Top P, or Top K. Since they are all a little different, I basically had to write unique types in Go for each one I wanted to support.</p><p>Beyond the various nuances of each LLM, Stable Diffusion is an entirely different animal. Instead of receiving a text based response, Stable Diffusion sends back image data. So, I had to think through how to deal with that, and save the results to disk. It wasn&apos;t too hard to figure out, but I did have to add logic to my code to give an error when the user was trying to do something that didn&apos;t make sense with Stable Diffusion, like starting an interactive chat session.</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.micahwalter.com/content/images/2023/11/chat-cli-3.png" class="kg-image" alt="Building a Generative AI CLI with Amazon Bedrock and Go" loading="lazy" width="1996" height="426" srcset="https://www.micahwalter.com/content/images/size/w600/2023/11/chat-cli-3.png 600w, https://www.micahwalter.com/content/images/size/w1000/2023/11/chat-cli-3.png 1000w, https://www.micahwalter.com/content/images/size/w1600/2023/11/chat-cli-3.png 1600w, https://www.micahwalter.com/content/images/2023/11/chat-cli-3.png 1996w" sizes="(min-width: 1200px) 1200px"></figure><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.micahwalter.com/content/images/2023/11/output-1698635369.jpg" class="kg-image" alt="Building a Generative AI CLI with Amazon Bedrock and Go" loading="lazy" width="512" height="512"></figure><h2 id="the-current-state-of-things-and-things-to-come">The current state of things and things to come</h2><p>The program is now in what I would call a &quot;working&quot; state. You can clone the repository and compile it yourself and give it a go. Here is what you can currently do:</p><ul><li>You can enter an interactive chat session with Anthropic Claude.</li><li>Within an interactive chat you can save and load your chat transcript to disk</li><li>You can send a single prompt to Bedrock from the command line</li><li>You can use the <code>--model-id</code> flag to select which supported LLM you wish to use</li><li>You can use the <code>--stream</code> flag to get a streaming response from a supported model</li><li>You can pipe a file in from <code>stdin</code> and combine with a prompt to do things like &quot;explain this document to me&quot;</li><li>You can use Stable Diffusion from the command line to generate and save images to disk</li></ul><p>I have a number of thoughts for future additions, but here are the near terms updates I plan to make:</p><ul><li>Ability to send a source image to Stable Diffusion</li><li>Ability to save settings to a configuration file</li><li>Un-hard-code all the LLM settings and create flags for each of them</li><li>Implement additional functionality available through the SDK like listing of available models</li><li>Setting up a documentation website for the project</li><li>Figure out how to sign binaries for easy install</li></ul><h2 id="help">Help!</h2><p>Overall this has been a fun project. I&apos;ve learned quite a bit about Generative AI, Large Language Models, Foundation Models, and have had some fun learning more about Go and building command line interfaces. I&apos;d love some help! If you&apos;d like to try chat-cli on your own, contribute to the code, suggest ideas or comment on my coding skills, please feel free to do so <a href="https://github.com/go-micah/chat-cli?ref=micahwalter.com">right here</a>.</p>]]></content:encoded></item><item><title><![CDATA[Running Go Programs on AWS App Runner]]></title><description><![CDATA[AWS App Runner was launched in 2021, and offers developers an incredibly easy way to deploy web applications.]]></description><link>https://www.micahwalter.com/running-go-programs-on-aws-app-runner/</link><guid isPermaLink="false">63ed8dfda48385003df98c26</guid><category><![CDATA[TIL]]></category><category><![CDATA[Go]]></category><category><![CDATA[Docker]]></category><category><![CDATA[AWS]]></category><category><![CDATA[AWS App Runner]]></category><dc:creator><![CDATA[Micah Walter]]></dc:creator><pubDate>Thu, 16 Feb 2023 02:04:19 GMT</pubDate><media:content url="https://www.micahwalter.com/content/images/2023/02/APC_0607.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://www.micahwalter.com/content/images/2023/02/APC_0607.jpg" alt="Running Go Programs on AWS App Runner"><p>I spent some time this week thinking about deploying Go programs and decided to learn how to containerize Go and in that process also decided to take a look at other ways to run Go on AWS. It turns out there are many options.</p><p>When I think about compute, there&apos;s basically three main categories of how I can run my code:</p><ol><li>On a server</li><li>On a container, on one of the many ways to run containers, including on servers</li><li>On AWS Lambda</li></ol><p>In my <a href="https://www.micahwalter.com/getting-going-with-go/">second post</a> I talked briefly about running Go on AWS Lambda. I got it working pretty quickly, and it&apos;s likely a topic I&apos;ll come back to in more detail as I progress with the language. But, serverless compute isn&apos;t always the right choice, and so I thought I&apos;d have a look at containerizing a Go program. (Interestingly, you can run a container on AWS Lambda--something I&apos;m sure to experiment with in the future.)</p><p>Containerizing a Go program is pretty simple. I created a basic <a href="https://github.com/go-micah/hello-docker?ref=micahwalter.com">hello-docker</a> repository and added the following code:</p><pre><code>package main

import (
	&quot;fmt&quot;
	&quot;net/http&quot;
)

func hello(w http.ResponseWriter, req *http.Request) {

	fmt.Fprintf(w, &quot;Hello, Docker.\n&quot;)
}

func main() {

	http.HandleFunc(&quot;/&quot;, hello)

	http.ListenAndServe(&quot;:3000&quot;, nil)
}
</code></pre><p>This is a super simple program that creates a web server using Go&apos;s <a href="https://pkg.go.dev/net/http?ref=micahwalter.com">net/http</a> package found in the standard library. The main function adds a handler for the <code>/</code> route and sets up a listener on port 3000.</p><p>To containerize this, I just created a Dockerfile that looks like this:</p><pre><code>FROM golang:1.19-alpine

WORKDIR /app

COPY go.mod ./
COPY go.sum ./

RUN go mod download

COPY *.go ./

RUN go build -o /hello-docker

EXPOSE 3000

CMD [ &quot;/hello-docker&quot; ]
</code></pre><p>This Dockerfile tells docker how to build my program, how to run it, and opens port 3000. Now I can build my docker image and ship it to whatever container platform I&apos;d like.</p><h2 id="aws-app-runner">AWS App Runner</h2><p>The first container service that came to mind was <a href="https://aws.amazon.com/apprunner?ref=micahwalter.com">AWS App Runner</a>. AWS App Runner was launched in 2021, and offers developers an incredibly easy way to deploy web applications. It handles all the load balancing, auto-scaling, logging and monitoring for you. No servers to manage, no provisioning or configuring software packages. It just works.</p><p>It turns out, there are two ways to deploy a Go app on AWS App Runner--from a container or from your source code.</p><p>Creating an app from source code just requires you to connect AWS App Runner to your GitHub repo, configure a few settings and your&apos;e done. You don&apos;t even need the Dockerfile!</p><p>Here are some notes on deploying my <code>hello-docker</code> web application on AWS App Runner.</p><h3 id="deploying-from-source-code">Deploying from source code</h3><ol><li>The console will help you connect to GitHub, link your repo, and select your branch</li><li>Your repo doesn&apos;t need a Dockerfile</li><li>You can choose to use an <code>apprunner.yml</code> config file, or set the basic config within the console for build and start commands.</li><li>My build command looked like <code>go build -o /hello-docker</code></li><li>My start command looked like <code>/hello-docker</code></li><li>You can set up automatic builds on every update to your GitHub branch or update manually</li></ol><h3 id="deploying-from-a-container">Deploying from a container</h3><ol><li>First you need to build the container locally and push it to <a href="https://aws.amazon.com/ecr/?ref=micahwalter.com">Amazon Elastic Container Registry</a> (ECR)</li><li>You can choose from ECR private or ECR public repositories when setting up your service</li><li>Your source code won&apos;t require an <code>apprunner.yml</code> config file</li><li>You will need a Dockerfile similar to the one I pasted above to build your container image</li><li>One benefit is that your container on ECR can be re-used on various other container infrastructure like ECS, EKS, Beanstalk, and more. This seems very appealing since you can easily switch services in the future.</li><li>You can choose to do automatic deployments whenever you push a new image to ECR or update manually</li></ol><p>I went through the paces of deploying both scenarios and they both worked equally well. I&apos;m not entirely sure which is better, however I am leaning toward the docker based version since it seems more flexible and less concerned with the specifics of AWS App Runner itself (no need for additional config files, etc.)</p><p>Here&apos;s some additional nice things I noticed when poking at AWS App Runner.</p><ul><li>You can pause and resume an AWS App Runner service to save money while in development</li><li>You can set up a <a href="https://docs.aws.amazon.com/apprunner/latest/dg/network.html?ref=micahwalter.com">VPC Endpoint</a> to connect your AWS App Runner service to resources inside a VPC like an Amazon RDS database or an Amazon EC2 Instance.</li><li>You can set up private endpoints and use AWS App Runner to host an internal API</li><li>AWS App Runner handles auto-scaling, load balancing and custom domains</li><li>You get built in observability with X-Ray as well as logging and metrics with Amazon CloudWatch</li></ul><p>Overall I think AWS App Runner is a great way to host Go programs. I&apos;m eager to continue working with it and see what else it can do. But, my favorite thing about AWS App Runner so far is the simplicity. The ability to point at a GitHub repo and launch a web app is super nice and a great way to rapidly prototype ideas on the Go.</p>]]></content:encoded></item><item><title><![CDATA[Go Packages, Go Docs, and the Distance Image]]></title><description><![CDATA[I think Go has taken a really smart approach to package and dependency management by simplifying things, removing the need for a complex package manager, and creating a global namespace.]]></description><link>https://www.micahwalter.com/go-packages-go-docs-and-the-distance-image/</link><guid isPermaLink="false">63ea5c238b9d36003d201385</guid><category><![CDATA[TIL]]></category><category><![CDATA[Go]]></category><category><![CDATA[Imaging]]></category><dc:creator><![CDATA[Micah Walter]]></dc:creator><pubDate>Mon, 13 Feb 2023 15:53:30 GMT</pubDate><media:content url="https://www.micahwalter.com/content/images/2023/02/IMG_1029.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://www.micahwalter.com/content/images/2023/02/IMG_1029.jpg" alt="Go Packages, Go Docs, and the Distance Image"><p>The past couple weeks have been pretty productive in terms of my mission to learn <a href="https://go.dev/?ref=micahwalter.com">Go</a>. I started reading this excellent book called &quot;<a href="https://www.amazon.com/Programming-Language-Addison-Wesley-Professional-Computing/dp/0134190440?ref=micahwalter.com">The Go Programming Language</a>&quot; by Alan Donovan and Brian Kernighan. It&apos;s been helpful because it does a good job at explaining why things are the way they are in Go, while working your way through each core principal. I&apos;m about 15% through the book already.</p><p>I also spent a good deal of time learning what I could about <a href="https://pkg.go.dev/?ref=micahwalter.com">packages</a> in Go. This seems to be a pretty important core concept, and something I&apos;ve struggled with in other languages like Python and Node. I think Go has taken a really smart approach to package and dependency management by simplifying things, removing the need for a complex package manager, and creating a <a href="https://en.wikipedia.org/wiki/Global_Namespace?ref=micahwalter.com">global namespace</a> by just piggybacking off the World Wide Web&apos;s global namespace.</p><p>I also started building a <a href="https://github.com/go-micah/imaging?ref=micahwalter.com">package of my own</a> to collect together some basic image processing functions. It&apos;s really just an exercise to learn more about Go and about building and documenting packages, but also has been a fun way to remind myself of some of the interesting concepts I learned about many years ago while studying <a href="https://www.rit.edu/study/photographic-sciences-bs?ref=micahwalter.com">imaging in college</a>.</p><p>Here are my notes.</p><h2 id="i-learned-all-about-go-packages">I learned all about Go Packages</h2><p>Packages in Go are a core concept to understand. Here are some key takeaways:</p><ul><li>I&apos;m not entirely sure what the difference is between a &quot;package&quot; and a &quot;module&quot; in Go, or if there even is a difference. Packages appear to be collections of Go files that can be imported into another Go program. Modules appear to be referenced in the form of <code>go mod</code> which is a command line tool that does the actual importing and documenting of versions.</li><li>There is a special package called <code>main</code> that every Go program implements once and it&apos;s where your program begins. A Go Package doesn&apos;t need to have a <code>main</code> package.</li><li>Packages can span multiple files and folders and your package namespace can use these folders to divide things up into logical groups. For example, you can have a package called &quot;imaging&quot; with a sub-folder called &quot;generators&quot; and you can import &quot;generators&quot; separately and parallel to anything else found within the &quot;imaging&quot; package.</li><li>Your Go program can have many packages within the code-base. They get imported in the same way as a third party package from GitHub or elsewhere. I&apos;m not entirely sure how Go works out which one to import, but it seems to prioritize local packages first.</li><li>The namespace is global, which is nice because someone can publish a package at <code>https://github.com/username/imaging</code> and I can publish a package at <code>https://github.com/go-micah/imaging</code> and we can import both, giving one or both an alias so they don&apos;t conflict in the program we are writing.</li><li>There is a website called <a href="https://pkg.go.dev/?ref=micahwalter.com">pkg.go.dev</a> where you can search for and browse packages and documentation. As a developer you don&apos;t need to upload your packages, you just let the site know you have one and it pulls in all the details from wherever you host your code. This is much nicer than PyPi or NPM in my opinion because there is always just a single source of truth for your code.</li></ul><h2 id="i-learned-a-little-about-go-documentation">I learned a little about Go Documentation</h2><p>Documentation in Go is pretty simple as well. In a nutshell, just add comments to your code.</p><ul><li>There is an old thing called <code>godoc</code> and there is a new thing called <code>pkgsite</code> which both allow you to view your docs in a web browser. The newer version presents a website that looks exactly like <code>pkg.go.dev</code> so you can preview how your documentation will appear once it&apos;s been crawled.</li><li>The official docs on writing docs leaves me a little wanting. It&apos;s basically this <a href="https://go.dev/blog/godoc?ref=micahwalter.com">blog post</a>, which outlines most of what you need to know. At the top there is a link to <a>this page</a>, which has all the details of how to do things the right way. I also found <a href="https://mdaverde.com/posts/golang-local-docs/?ref=micahwalter.com">this blog post</a> useful in terms of getting <code>pkgsite</code> working.</li><li>You can add an additional file to the top level of a package called <code>doc.go</code> where you can add high level documentation and examples.</li></ul><h2 id="i-made-a-package-of-my-own-and-a-distance-image-function">I made a package of my own and a &quot;Distance Image&quot; function</h2><p>As I mentioned earlier, I decided to learn by doing and created a package called <code>imaging</code>. This package currently has just one public function, but I plan to keep adding to it.</p><p>The function is called &quot;Dist&quot; and allows anyone to generate something called a &quot;Distance Image&quot; where the value of each pixel is relative to the distance to the center of the image. This is a useful thing to have anytime you need a quick test image.</p><p>It winds up looking something like this!</p><figure class="kg-card kg-image-card"><img src="https://www.micahwalter.com/content/images/2023/02/dist.png" class="kg-image" alt="Go Packages, Go Docs, and the Distance Image" loading="lazy" width="512" height="512"></figure><p>To do this, I made two functions in my imaging package. This first is a public function called <code>Dist</code> which takes the desired height and width of the image. (Capitalizing the first letter of a function makes it public.) The second is a private function called <code>calculateDistance</code> which uses the quadratic equation to calculate distance from any pixel to the center of the image. (There is some fun with rounding and converting ints to floats, which I will dig into in another post.)</p><p>Within the <code>Dist</code> function I wrote up a nested <code>for</code> loop, which will traverse the image, pixel by pixel. This is an important pattern to know about when dealing with images, and maybe in a future version, I will move it out to a <code>draw</code> function as I am sure I&apos;ll need to use it more than once.</p><p>You can already import this package into your own Go program like this:</p><pre><code>import &quot;https://github.com/go-micah/imaging&quot;
</code></pre><p>And, you can already <a href="https://pkg.go.dev/github.com/go-micah/imaging?ref=micahwalter.com">read the docs here</a>.</p><p>That&apos;s all for now. Yay!</p>]]></content:encoded></item><item><title><![CDATA[Getting going with Go]]></title><description><![CDATA[<p>I&apos;ve been getting going with <a href="https://go.dev/?ref=micahwalter.com">Go</a> for about a week now and I&apos;ve already learned so much! I realized last weekend that I had two primary interests I want to focus on throughout my journey. The first is that I really want to learn the language</p>]]></description><link>https://www.micahwalter.com/getting-going-with-go/</link><guid isPermaLink="false">63d42d9160d417003db86911</guid><category><![CDATA[TIL]]></category><category><![CDATA[Go]]></category><category><![CDATA[Lambda]]></category><category><![CDATA[AWS]]></category><dc:creator><![CDATA[Micah Walter]]></dc:creator><pubDate>Fri, 27 Jan 2023 20:08:29 GMT</pubDate><media:content url="https://www.micahwalter.com/content/images/2023/01/IMG_4196.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://www.micahwalter.com/content/images/2023/01/IMG_4196.jpg" alt="Getting going with Go"><p>I&apos;ve been getting going with <a href="https://go.dev/?ref=micahwalter.com">Go</a> for about a week now and I&apos;ve already learned so much! I realized last weekend that I had two primary interests I want to focus on throughout my journey. The first is that I really want to learn the language itself, and get to a point where I can confidently type code and work through my ideas a reasonable pace. The second is that I am really interested in how developers can use Go on AWS.</p><p>So here&apos;s what I&apos;ve been working on.</p><p>I spent more time going through the <a href="https://go.dev/tour?ref=micahwalter.com">Tour of Go</a> on the Go website. There are some things about Go that feel a little awkward at first, so I&apos;m trying my best to rewire my brain a little.</p><p>For example, when declaring a variable in Go, you put the name of the variable first, and then its type.</p><pre><code>var familyName string = &quot;Walter&quot;
</code></pre><p>Also, when declaring a function, you put the return type at the end, like this:</p><pre><code>func getName(familyName string) string {
	return &quot;Walter&quot;
}
</code></pre><p>I also learned that if you capitalize the first letter of anything (variable names or function names, etc.) Go makes that object available (exported) to other packages and programs.</p><pre><code>var FamilyName string
var familyName string
</code></pre><p>The other big thing I see in Go is that there&apos;s all kinds of shorthand expressions. This seems handy, but I&apos;m sure it&apos;s gonna take some time to learn all of them before I can really read someone else&apos;s Go program.</p><p>For example, instead of this:</p><pre><code>var familyName string = &quot;Walter&quot;
</code></pre><p>You could just type this:</p><pre><code>familyName := &quot;Walter&quot;
</code></pre><p>Go will decide what the correct data type is on its own.</p><h2 id="playgrounds">Playgrounds</h2><p>It&apos;s pretty easy to create a folder and start hacking in Go on your laptop, but I really like having a browser based playground to try things out quickly. There is a nice, official, <a href="https://go.dev/play/?ref=micahwalter.com">Playground</a> on the Go website, where you can run code easily enough, but I also found this &quot;<a href="https://goplay.tools/?ref=micahwalter.com">Better Go Playground</a>&quot; which has some additional features that I find pretty handy--the main one being the ability to save and share snippets.</p><p>For example, I decided to try my hand at solving &quot;<a href="https://en.wikipedia.org/wiki/Fizz_buzz?ref=micahwalter.com">FizzBuzz</a>&quot; in Go and saved the <a href="https://goplay.tools/snippet/Kcd9slXvlLy?ref=micahwalter.com">snippet here.</a></p><p>The &quot;Go Better Playground&quot; is a great tool for learning as it makes it super easy to try things out without the overhead of thinking about your local developer setup, or creating a repository. I can even see it being useful if I&apos;m working on a larger project and just need a space to test some code, without having to compile the entire project.</p><h2 id="as-for-fizzbuzz">As for FizzBuzz ...</h2><p>FizzBuzz is one of the most common white-boarding exercises that technical interviewers use to weed out candidates in interviews. I first came across FizzBuzz when interviewing for a job about 10 years ago. When the interviewer brought it up, I had zero idea what she was talking about. I proceeded to work through the challenge, using a mix bag of languages and syntax, but ultimately solved the puzzle.</p><p>It&apos;s a fun challenge, but I have opinions about white boarding during interviews. More on that in another post I guess! And, in case you&#x2019;re wondering, they offered me the job, but I ended up turning it down for other reasons.</p><p>FizzBuzz in Go was pretty easy to work through. It helped reinforce how to create a simple <code>for</code> loop and how to write a basic function. I had to think about converting data types from one to another, and I also learned about the <code>strconv</code> library, which came in handy when I needed to convert integers to strings. Yay, FizzBuzz!</p><h2 id="go-on-aws">Go on AWS</h2><p>I work at AWS, so it makes sense I&apos;d want to learn about running Go on AWS. To get started, I figured I&apos;d try and build a simple &quot;Hello Lambda&quot; function in Go. I wound up making two.</p><h3 id="hello-lambda">Hello, Lambda</h3><p>The first function I made was as bare bones as I could do. I mainly wanted to go through the process of creating a <a href="https://aws.amazon.com/lambda/?ref=micahwalter.com">AWS Lambda</a> function in Go, and deploying it to Lambda via the AWS Console. It was pretty easy.</p><ol><li>A Lambda function in Go needs to import the <a>AWS Lambda Go</a> package.</li><li>The <code>main</code> function in your <code>package main</code> needs to start a handler function. This can be called whatever you want (I called my handler <code>hello</code>) and it&apos;s what Lambda will run when you invoke your function.</li><li>Once your function is ready, it needs to be compiled to run on Linux using the following command: <code>GOOS=linux GOARCH=amd64 go build -o &lt;your-executible&gt; &lt;your-go-source-file.go&gt;</code></li><li>After you&apos;ve compiled your function, it needs to be zipped.</li><li>Then you just create a new Lambda function in the console, selecting Go as the runtime, and upload your Zip file.</li><li>Finally, you will need to change the setting for the handler to the name of the executable file (not the handler function name)</li><li>I&apos;ve got a few additional notes and code <a href="https://github.com/go-micah/hello-lambda?ref=micahwalter.com">here</a>.</li></ol><h3 id="hello-serverless-application-model">Hello, Serverless Application Model</h3><p>Dealing with Go in the AWS Console works, but there are some limitations. You can&apos;t live-edit a Go function in the AWS Lambda console. This means that you need to write, edit, and test your Go code somewhere else before deploying it to AWS. This is ok at first, but once you get into the weeds of developing something complex, the development lifecycle might get pretty tiresome. To alleviate this concern, I started to explore the various infrastructure as code frameworks available (there&apos;s a bunch now!) for AWS Lambda and Go.</p><p>After some quick research, I decided to explore the <a href="https://aws.amazon.com/serverless/sam/?ref=micahwalter.com">AWS Serverless Application Model</a> (SAM). I&apos;ve used SAM in the past with other languages. It was super easy.</p><p>SAM provides a very nice toolset for Go, and even has a built in template for setting up a basic API with a Lambda function. You just install the SAM CLI and run <code>sam init</code> and follow the prompts, selecting Go as your runtime. The CLI will then build you a project with a SAM template, a basic <code>Hello, Lambda</code> function, and a Makefile to automate the build process. You can then use the SAM CLI to deploy your Lambda function and API Gateway to your AWS account.</p><p><a href="https://github.com/go-micah/hello-lambda-api-sam/tree/bafbb2c4bf9a659649b1ea5b7575dd54d4de2c4d?ref=micahwalter.com">Here</a> is what the SAM CLI built for me. I haven&apos;t really made any changes so far. I just ran through the deploy process and got my simple API to work. This is fun! Now I have a way to build out a Go based API on AWS Lambda, and I can use SAM to test and debug my code locally.</p><p>That&apos;s all for now. Now Go away!</p>]]></content:encoded></item><item><title><![CDATA[I'm gonna learn Go!]]></title><description><![CDATA[Even though I've got some experience with Go, I'm gonna set out on this journey as if I'd just learned of Go today.]]></description><link>https://www.micahwalter.com/im-gonna-learn-go/</link><guid isPermaLink="false">63c9f1576f36fa004d4e73cf</guid><category><![CDATA[TIL]]></category><category><![CDATA[Go]]></category><category><![CDATA[AWS]]></category><category><![CDATA[Lambda]]></category><dc:creator><![CDATA[Micah Walter]]></dc:creator><pubDate>Fri, 20 Jan 2023 01:48:14 GMT</pubDate><media:content url="https://www.micahwalter.com/content/images/2023/01/IMG_2860.JPG" medium="image"/><content:encoded><![CDATA[<img src="https://www.micahwalter.com/content/images/2023/01/IMG_2860.JPG" alt="I&apos;m gonna learn Go!"><p>I&apos;m gonna learn Go! Not the <a href="https://en.wikipedia.org/wiki/Go_(game)?ref=micahwalter.com">2500 year old Chinese board game</a>, the <a href="https://en.wikipedia.org/wiki/Go_(programming_language)?ref=micahwalter.com">13 year old programming language</a> developed at Google.</p><p>I have a little experience with Go, but not much. Years ago I wanted to learn Go, but my efforts stalled. Eventually, I learned enough to build a few AWS Lambda functions, and later I even contributed code to an open source project I care about. But, to be honest, it was all mostly copy and paste, and I never felt like I really &quot;learned&quot; Go.</p><p>So now, I&apos;d like to try again, and learn it properly, from scratch.</p><h2 id="why-go">Why Go ?</h2><p>I&apos;ve been interested in Go for a long time. It appeals to me for a number of reasons.</p><ol><li>It&apos;s pretty easy to read. I like the structure of the language, and the consistency and style that programmers are encouraged to utilize. It&apos;s clean, and pretty readable, once you learn all the various shorthand.</li><li>It&apos;s fast! Go is a compiled language, which means you compile your code into a binary file for the underlying operating system ahead of running the code. This offers lots of efficiencies and performance benefits. I like fast.</li><li>It&apos;s statically typed? - OK, .. I admit, this seems like one of those things I may not directly benefit from at first. I mean, I get what it means to be a statically typed language, and I understand how that could be beneficial down the road. For now though, I am guessing it will just feel like more work and could be conceptually more difficult to understand. But, this is one of those &quot;<a href="https://go.dev/solutions/?ref=micahwalter.com#case-studies">Why Go?</a>&quot; reasons you will read about.</li><li>Dependency management seems good. Go has a really pleasant way of dealing with dependencies. I don&apos;t yet fully understand how it works, but there&apos;s no need for <code>pip</code> of <code>npm</code> or <code>yarn</code> and all that noise. It&apos;s just built in and uses <code>git</code> repos. Seems nice!</li><li>It&apos;s a supported runtime on <a href="https://docs.aws.amazon.com/lambda/latest/dg/lambda-golang.html?ref=micahwalter.com">AWS Lambda</a>. I&apos;m keen to use Go on Lambda, so that&apos;s also nice.</li><li>It&apos;s one of the <a href="https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-go.html?ref=micahwalter.com">supported languages</a> you can use to write <a href="https://docs.aws.amazon.com/cdk/index.html?ref=micahwalter.com">CDK</a> code in. I&apos;m a huge fan of the CDK. You can of course mix and match your CDK language with your Lambda language, but it&apos;s comforting to know you could do it all in Go!</li><li>I&apos;m a curious person who wants to learn something new.</li></ol><p>That last one is really my main reason for continuing to explore Go. I&apos;m pretty confident with Python, which is the language I run into most of the time at my job. I can find my way around a JavaScript or even a TypeScript program pretty easily. Don&apos;t get me started on PHP, and I&apos;d probably have to break out the college text books to talk about C++. I&apos;m genuinely just curious to try something new, something outside my comfort zone, and I think the statically typed aspect of Go might help reinforce some concepts I haven&apos;t had much exposure to.</p><h2 id="where-to-start">Where to start?</h2><p>Even though I&apos;ve got some experience with Go, I&apos;m gonna set out on this journey as if I&apos;d just learned of Go today. To get myself started, I have a few ideas.</p><ol><li>The <a href="https://go.dev/?ref=micahwalter.com">Go website</a> has loads of tutorials and getting started resources. I&apos;m gonna go through all that to begin learning the core concepts of the language. In other words, I&apos;m gonna read about Go.</li><li>I&apos;m also gonna learn by doing. I&apos;m gonna spend some time each day hacking on some simple projects. These will likely be very AWS focused, since that&apos;s my main area of interest.</li><li>I&apos;m gonna share my learning with you all via this website, and I&apos;ll publish all my code on GitHub. A while back I created a GitHub Organization just for my Go code. I&apos;ve resurrected it, and I&apos;ll use it as a place to share my notes, my code, and anything else that comes my way. It&apos;s called &quot;<a href="https://github.com/go-micah?ref=micahwalter.com">go-micah</a>&quot;, naturally!</li><li>I&apos;m also planning to make more contributions to a few open source projects I love.</li></ol><h2 id="what-ive-learned-so-far">What I&apos;ve learned so far</h2><p>Here are a handful of notes on what I&apos;ve learned so far.</p><ol><li>The online tutorials a super good. The &quot;<a href="https://go.dev/tour/?ref=micahwalter.com">Tour of Go</a>&quot; is interactive and thorough, and a great way to learn basic concepts. I already learned that Go only has one looping construct in the form of a <code>for</code> loop. That makes total sense!</li><li>There is something called <code>fmt</code>. I&apos;m just starting to explore the standard library. I keep saying <code>fmt</code> like &quot;fumpt.&quot; That can&apos;t be right.</li><li>There is a <a href="https://go.dev/play/?ref=micahwalter.com">Playground</a> to try things quickly.</li><li>You can explore and publish your own packages via <a href="https://pkg.go.dev/?ref=micahwalter.com">pkg.go.dev</a>. One thing I noticed is you don&apos;t need to upload your code here. You just make it aware of your code on GitHub or other places and it pulls it in.</li><li>Getting set up to code isn&apos;t too hard anymore. I recall Go being a little difficult to install and configure. That no longer seems to be the case, and in fact, if you use <a href="https://github.com/features/codespaces?ref=micahwalter.com">GitHub Codespaces</a> it&apos;s already installed and ready to go.</li><li>There is something called <code>go mod</code> and although I know it&apos;s about managing dependancies, I don&apos;t really understand how it works just yet. I mean, it works, but how?!</li><li>Today I wrote up a simple <a href="https://github.com/go-micah/hello-lambda?ref=micahwalter.com">Hello World</a> application in Go and deployed it to Lambda. I&apos;ll write up my notes on this in my next post. The short version is...it worked!</li></ol><p>I have to say, I&apos;m excited to learn something new, purely for my own enjoyment. I hope you&apos;ll follow my progress, and if you are also learning Go, please feel free to reach out!</p>]]></content:encoded></item></channel></rss>