Tools to Organize Your Life
Much productivity advice on the internet is too complicated and not actually that helpful. Complicated systems are less likely to be used due to the friction of using them and are more brittle in the face of changing needs. You are better off use basic, flexible systems; you are more likely to use simple systems and simple systems can adapt to change more easily. There are only a few tools you need to completely run your personal life....
Keep Email Useful
I get the impression that a lot of people are overwhelmed by their personal email inbox nowadays and get so much email that they’ve more or less given up on it. I don’t have that problem and that’s by design, not by accident. This post explains the rules I use to keep my personal email useful and very manageable. Unsubscribe aggressively Any time you give your email address out nowadays, you will get put on a mailing list....
Echo Router Parameters
I regularly have to look up how to create an Echo router context with (a) path parameters and (b) query parameters, so I’m making this post as a cheat sheet for my future self. Path parameters Example: /some/random/path/:id // create your context ctx := echo.New().NewContext(request, response) // add your path param ctx.SetParamNames("id") ctx.SetParamValues("foo") Query parameters Example: /some/random/path?key1=value1&key2=value2 // create your request request := httptest.NewRequest(http.MethodPost, "/some/random/path", nil) // get existing query params query := request....
Go Backoff Algorithms
I ran across a blog post by Josh Bleecher Snyder today which has some beautiful backoff algorithms in Go. Capturing them here in case his blog ever goes offline. Algorithm 1 func do(ctx context.Context) error { const ( maxAttempts = 10 baseDelay = 1 * time.Second maxDelay = 60 * time.Second ) delay := baseDelay for attempt := range maxAttempts { err := request(ctx) if err == nil { return nil } delay *= 2 delay = min(delay, maxDelay) jitter := multiplyDuration(delay, rand....
How to view and remove routes on macOS
Today I needed to remove a bad route on macOS. Normally I just reboot to do that, but I decided to learn how to do it without rebooting. Here’s how I did it. First, view the routes to confirm the route is bad: netstat -rn | grep IP_ADDR Grab the IP you care about from the “Destination” column. Use it to delete the route: sudo route -n delete DEST_IP_ADDR Done!
Fixing a filename in git on a case insensitive filesystem
My work laptop was provisioned with a case-insensitive filesystem for some strange reason. This makes renaming stuff in a git repo “fun”: $mv README.md readme.md mv: 'README.md' and 'readme.md' are the same file Here’s a workaround for this problem: # give the file a temp name git mv README.md readme_temp.md git com -m "Rename 1 of 2" # then name it what you actually want to call it git mv readme_temp....
Grep's Buffering + Pipes
I got bit by this again today, so I’m writing it down so I can reference it later. When running docker logs -f CONTAINER_NAME | grep -v "foo" | jq, it is important to consider grep’s buffers. I am using GNU grep and, by default, it uses block buffering when not connected to a terminal (which is my case, since I piped it to jq). This means jq doesn’t get any input until a large-ish amount of text (4k?...
Playing around with trees in Golang
I was playing around with implementing Depth First Search (DFS) and Breadth First Search (BFS) in Go today. I made a tree which looked like this… 0 / \ 1 2 / \ / \ 3 4 5 6 / \ 7 8 I then made some Go code to walk the tree using DFS and BFS: package main import "fmt" // Node is a very basic struct which represents // a node in the tree....
Enums in Go Part Deux - Marshaling and Unmarshaling!
My blog post from yesterday made me think… how can you marshal and unmarshal enums in Go correctly? So I modified internal/coffee/coffee.go and added a MarshalText() and UnmarshalText() methods: package coffee import ( "fmt" "strings" ) //go:generate stringer -linecomment -type=Coffee type Coffee int const ( Drip Coffee = iota // drip coffee Latte // latte Breve // breve Cappuccino // cappuccino ) func (c Coffee) MarshalText() ([]byte, error) { return []byte(c....
Enums in Go
I was asked yesterday how you implement enums in Go. I didn’t know, so I spent some time this morning learning how to do it. It turns out this is ridiculously easy to do and Go has the stringer tool which makes it super simple. (stringer codegens the code which prints your enum as a string.) Example I created a repo with the following structure: go.mod main.go internal/coffee/coffee.go internal/coffee/coffee_string.go internal/coffee/coffee.go looks like this:...