Go Test Parallelism

This post documents some testing I did around whether unit tests in Golang are run in parallel. TLDR: Tests in a given package run serially, unless t.Parallel() is specified. To test this, I created two files in a directory named gotest: $ ls one_test.go two_test.go // one_test.go package main import ( "fmt" "testing" "time" ) func TestOne(t *testing.T) { fmt.Println("1 starts:", time.Now().String()) time.Sleep(5 * time.Second) fmt.Println("1 ends:", time.Now().String()) } // two_test....

2024-10-18

Go sub-slice gotchas

Thanks to Julia Evan’s latest post, I learned that creating new slices by sub-slicing an existing slice has an important caveat: They can sometimes use the same backing array! 😬 This is important to understand if you mutate the sub-slice. Take the below example, wherein we accidentally mutate s1! package main import ( "fmt" ) func main() { s1 := []int{0, 1, 2, 3, 4, 5} // len == 6, capacity == 6 s2 := s1[1:5] // len == 4, capacity == 5 // Modifies both s1 and s2, because they share the same backing array....

2024-08-11

Configuring a Git pre-push hook to run unit tests

A coworker turned me onto this lovely technique the other day. You can use a git pre-push hook to run all of your Golang unit tests before pushing. To do this, make a the following file: $YOUR_REPO/.git/hooks/pre-push The file must be executable. The file’s contents should be: #!/bin/sh if ! go test ./... ; then echo echo "Rejecting commit. Unit tests failed." echo exit 1 fi Easy peasy.

2024-06-26

Running a subset of Go tests

It is often useful to run a subset of the tests in a Go project. You might do this because you only want to see test results for one package or to run tests faster. For these examples, assume your project is a Go module named examplemodule. It has the following structure: examplemodule |_ go.mod |_ go.sum |_ internal |_ foo | |_ foo.go | |_ foo_test.go |_ bar |_ bar....

2024-03-07

Max and min integer values in Golang

Today I needed to use the maximum unsigned 64-bit integer value possible in Golang. Here is a short program I wrote with some help from Stack Overflow to help me remember how to calculate these without any dependencies. package main import "fmt" const ( minUint32 = uint32(0) maxUint32 = ^uint32(0) minUint64 = uint64(0) maxUint64 = ^uint64(0) minInt32 = int32(-maxInt32 - 1) maxInt32 = int32(maxUint32 >> 1) minInt64 = int64(-maxInt64 - 1) maxInt64 = int64(maxUint64 >> 1) ) func details[numeric int32 | int64 | uint32 | uint64](name string, num numeric) { fmt....

2024-03-05

Go build tags

Today I learned about Go build tags. Here’s some quick notes to help me remember how to use them. Assume you have directory like so: $ ls -1 extra.go go.mod main.go And main.go has contents: package main import "fmt" var numbers = []string{ "one", "two", } func main() { for _, number := range numbers { fmt.Println(number) } } And extra.go has contents: //go:build extrastuff package main func init() { numbers = append(numbers, "three", "four") } If you build without any tags, you get this:...

2024-01-03

Using gonew to easily create template repos

Now that I’ve been writing Golang for a while, when I start a new project, I typically know the sort of layout I’m looking for. I typically go for something like this: . β”œβ”€β”€ cmd β”‚ └── demo β”‚ └── main.go β”œβ”€β”€ go.mod β”œβ”€β”€ internal β”‚ └── subpkg β”‚ β”œβ”€β”€ subpkg.go β”‚ └── subpkg_test.go └── LICENSE And often there are lots of ascillary files that go along with this, like Makefiles, CI/CD config files, Dockerfiles, docker-compose files, etc....

2023-12-14

Checking an error's type in Golang

I was not very familiar with checking an error’s type in Golang, so I spent a few minutes learning about it today. It turns out that it’s incredibly easy to do. Running the below code shows the output: 2009/11/10 23:00:00 got custom error: err1 package main import ( "errors" "log" ) var ( customErr = errors.New("err1") // create a error, identified by its var name ) // oops always returns our custom error....

2023-12-07

Benchmarking Unnecessary Allocations

I’ve also been thinking more about unnecessary allocations in my Go code and how to avoid them by pre-declaring the length of a slice up front. Normally, I’d write something like this: var s []int for _, val := otherSlice { s = append(s, val) } Since I don’t specify the size of s, if otherSlice is large, the array underlying s might not be large enough to hold all the values; then a new array will have to be allocated and (I presume) all existing values copied out of it one at a time to fill the new array....

2023-09-30

Templating files with Golang

I recently went through How To Use Templates in Go to refresh my memory on Golang templates. I was reminded how great they are and learned several things along the way. I learned that the below syntaxes are equivalent: {{ . | len }} {{ (len .) }} Here is the program I wrote and tweaked along the way, to refresh my memory in the future: package main import ( "html/template" "os" "strings" ) type Pet struct { Name string Sex string Intact bool Age string Breed []string } var dogs = []Pet{ { // This is why you should use html/template and not text/template when // rendering HTML....

2023-09-19