On Code
A script for keeping go up to date on Linux
I use the following script to keep go up to date on my local machine without using a package manager. This is by no means elegant or efficient, but it gets the job done. It finds the current version of go by scraping the go.dev website with a very naive match, and then plops the resulting tarball onto my filesystem.
Raw link: getgoer.sh
#!/bin/zsh
## Usage:
## getgoer [install]
## getgoer alone will output the current and remote versions
## getgoer install will upgrade if the current vesrsion is different than the remote version
arch="linux-amd64"
function getLinks() {
curl https://go.dev/dl/ 2>/dev/null | awk '/download downloadBox(.*)/ {match($0, /href="(\/dl\/go([0-9]+\.[0-9]+\.[0-9]+)\.([^.]+)\..+)"/, arr); print arr[1]}'
}
links=$(getLinks)
function remoteVersion() {
echo $links | awk -v arch="${arch}" '$0~arch {match($1, /\/dl\/go([0-9]+\.[0-9]+\.[0-9]+)/, arr); print arr[1]}'
}
function installedVersion() {
go version | awk '{match($0, /go([0-9]+\.[0-9]+\.[0-9]+)/, arr); print arr[1]}'
}
function checkVersion() {
[[ "$(remoteVersion)" == "$(installedVersion)" ]]
return
}
function getDownloadLink() {
echo "https://go.dev$(echo $links | awk -v arch="${arch}" '$0~arch {print $1}')"
}
function upgrade() {
if checkVersion; then
echo "Current version $(installedVersion) is the same as upstream. Not doing anything"
return
fi
echo "current version is $(installedVersion). Downloading new version $(remoteVersion)."
fpath=/usr/local
sudo rm -r "${fpath}/go"
curl -L $(getDownloadLink) 2>/dev/null | sudo tar -C $fpath -vxz
}
if [[ "${1}" == "install" ]]; then
upgrade
else
echo "Current version: $(installedVersion)\nRemote version: $(remoteVersion)\nDownload link: $(getDownloadLink)"
checkVersion
fi
Unmarshalling a Unix timestamp to time.Time from JSON in go
Sometimes when working with remote APIs, you will come across dates formatted as Unix timestamps (an integer number of seconds since the epoch1). Go has a very nice native type for dealing with times, though, and it would be nice to be able to directly unmarshal2 to that type without doing the type conversions later. Fortunately, we can do easily do this by overriding the UnmarshalJSON
method.
To do this, we will create a custom type that embeds time.Time
:
Go For a Loop
Go, like many languages, has a for
loop. The snippet below can help to understand the versatility of these loops. This mechanism goes well beyond simply counting integers, but can be used to implement any number of looping patterns. The important thing to remember is that the second expression in the for loop definition controls the loop, and can be used with any function or method that returns a bool
, or any expression that evaluates to a bool
. Also remember that the three expressions are all optional1.
Attaching StringIO Data to a Mailgun Message
Recently I started using Mailgun for our outgoing messages. They have a very nice API, and take a lot of the heavy lifting out of creating multipart messages.
If you are using requests (or treq) to send the messages through their REST API, however, you may have noticed that you must specify “attachment” as the key, and an open file handle as the value. This works great if you are sending files from the filesystem, but if you need to send generated or in memory data as a file attachment, it just doesn’t work. Adding a name
attribute to the StringIO class does the trick:
A Picture is worth how many words?
i was playing around with some imaging code, and started wondering what it would look like to create some images out of text. I have worked with stenography in the past, but this time I didn’t want to hide the text, I wanted to pack the image with it.
First things first, I need some text. Time to turn to trusty Project Gutenberg. I will be using the text of Moby Dick for this project.