Generics in Go

Generics in Go were added about a year back in Go 1.18. In my experience they are great and they fix one of the biggest roadblocks in terms of writing reusable code in Go. I’ll illustrate that with an example.

First, do ensure that you have at least Go 1.18

$ go version
go version go1.19.1 darwin/amd64

Let’s consider a simple case of implementing a Map function in Go that maps an array (well, a slice) to another array (again, actually, a slice).

First, let’s start with a non-generic implementation

package main

import (
  "fmt"
)

func Map(input []int, mapFunc func(int)int) []int {
  output := make([]int, 0, len(input))
  for _, val := range input {
    output = append(output, mapFunc(val))
  }
  return output
}

func main() {
  input := []int {1,2,3}
  squared := func(x int) int {
    return x * x
  }
  output := Map(input, squared)
  fmt.Printf("%+v\n", output)
}

And now let’s generalize the Map function, notice that, in most cases, the caller wouldn’t change at all.

// A is the input type
// B is the output type
func Map[A any,B any](input []A, mapFunc func(A)B) []B {
  output := make([]B, 0, len(input))
  for _, val := range input {
    output = append(output, mapFunc(val))
  }
  return output
}

Common pitfalls of GitHub Actions

If you create GitHub Actions via GitHub’s UI by going to the URL of the form https://github.com///actions/new, it provides templates for setting up the build. However, the template is broken.

There are four problems with the default template

Read More

Bad and good ways to test code

Writing tests at an early-stage startup is always heatedly debated. If a function has one call, adding a unit test doubles the number of calls, this not only doubles the current work but even slows down future code changes 2X! Further, if the code is not finalized, it is legitimate to ask why even bother writing test code. Here’s a better way to write tests

Read More

GraphQL vs gRPC

RPC calls allow one service to call functions in another service as if it is a part of the same service. And unlike a REST API, one gets strong type checking. The two services can even be in different languages.  gRPC is a great framework for implementing an RPC service.

Another language-agnostic framework for making RPC calls is GraphQL. Many people don’t think of GraphQL that way, however, it can serve the same purpose.

Both GraphQL and gRPC are modeled as server and client-side frameworks. So, which one should you use?

GraphQL is a superior option when one is planning to build an API service that’s exposed to the Internet. Even more so, because multiple queries can be combined into one.

gRPC, however, is better for the use case where the gRPC server is a private service not exposed to the public network.

Infinite network timeouts in Java and Go

Java made a huge mistake of having no network timeouts. A network request can block a thread forever. Even Python did the same. The language designers should have chosen some conservative appropriate numbers instead.

What’s surprising is that the Go language repeated it!  Here’s a simple demo

Read More

Android: Catching NDK crashes

On Android catching Java exceptions is easy via UncaughtExceptionHandler. Catching NDK crashes is a bit more convoluted. Since the native stack is probably corrupted, you want the crash handler to run on a separate process. Also, since the system might be in an unstable shape, don’t send the crash report to your web server or do anything fancy. Just write the crash report to a file, and on the next restart of the app, send to your web server and delete it from the disk. I ended up using jndcrash package for this.

Read More