A collection of dev guides, tutorials and thoughts on various tech stacks, tools and programming languages.
This is a continuation of the common design patterns I found in my old code series, which I started in a previous post.
While going through some of the code I found a couple of instances where I was making copies of some structs, but I wasn’t using the built in copy() method. I was, instead, using some custom copy logic.
The reason for that was that the struct had some properties that were slices of other structs and if I were to use copy(), it would get me in trouble as there was a possibility that the source struct could be mutated.
This is a continuation of the common design patterns I found in my old code series, which I started in a previous post.
Another common pattern I found is the factory method pattern, which is a design pattern used to create different types of objects using the same interface.
This pattern is actually pretty common in Go. Some good example of this are the builtin I/O libraries:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 package main import ( "bytes" "encoding/csv" "fmt" "io" "os" ) func main() { f, _ := os.
I recently started going through some of my old code and I was trying to identify some common design patterns. I thought it could be a good memory exercise and refresher on software design patterns as it’s been quite some time since I last read through that.
And while I was doing that, I thought it might be a good idea to write about the patterns with the most occurrences.
If you’re building a micro-service architecture you’ll most likely end up using some sort of networking lib to manage the communication between services.
This is where gRPC fits in. I’m not gonna go through why it’s a good choice, most of the time, but let’s just say that interoperability between different programming languages becomes a lot better.
There’s also a decent amount of documentation and a relatively large community where you can find help.
Go has some pretty good support/tools for cross-compiling binaries for multiple platforms/architectures. Just check the $GOOS/$GOARCH env vars listed in the official documentation.
But sometimes, you may need to use some lib/code written in C that hasn’t been ported to Go. For this reason, there’s cgo, which you can use to call C code from your Go code. And while it can be straightforward to use when you run the binaries on the same platform you used to build them, it can be a bit of a mess when cross-compiling for platforms/architectures that are different.
In one of my previous posts, cross-compiling for Raspberry Pi with Docker, I wrote about and illustrated how the relatively new buildx command made it much easier to build and dump binaries on the host system.
Another useful feature of buildx is the ability to use different drivers when building images. As of today (10.10.2020), it supports 3 different drivers:
docker - uses the docker daemon built in builder (default).
If you’re using Github’s workflows for CI/CD and you need to use some of Docker’s experimental features, or you want to use buildx or maybe you just want to use some of the new dockerfile experimental syntaxes then you need to enable the experimental features for the CLI and probably the daemon too.
When running natively on Linux or macOS, it’s pretty easy.
To enable the experimental features for the CLI, you just need to add the following to your ~/.
If you find yourself having to emulate different CPU architectures in a Kubernetes environment you’ll probably end up running some version of binfmt as an init container or maybe manually run it once.
That would probably be ok in most cases, but wouldn’t work if, for example, you’re running multiple pod replicas on the same node concurrently (say, when you setup a CI that spawns pods for every job in your pipeline) or when nodes are autoscaled.
If you landed on this page, it means you probably have the same issue I’ve stumbled upon as well: I need to access some private Github repos while building a docker image but I don’t want any ssh keys or credentials to end up in the final image.
While there’s already ways to achieve this, the recent additions of buildx (first release was back in April 2019) and experimental dockerfile syntaxes (available from v18.
The Raspberry Pi is a pretty useful tool for quickly prototyping some IoT product, simulating an embedded environment, running a small Kubernetes cluster, etc; there are probably lots of reasons why you’d want to use one (or maybe not?).
As for developing software that can run on it, if you’re writing it in C or C++, there’s many ways to go about it:
Sync the code changes you make on the Pi and build it natively on it (via rsync, scp, SSHFS, git, etc) Use crosstool-ng to setup a toolchain and use it to cross-compile your software; then copy the resulting binaries onto the Pi Use a precompiled toolchain to cross-compile the software; then copy the binaries onto the Pi Develop directly on the Pi through an SSH session Use a containerized OS such as Balena And you can probably find many other creative ways developers came up with.