How to build, run and test go2 files locally
Tags: go, docker, generics
Published: 2020-08-16 14:58:41

I worked recently on an [in-memory key, value cache with Go](https://github.com/NdoleStudio/lfu-cache) and I used `interface{}` for the `key`, `value` types since I didn't want to restrict their usage to a specific type. Now with Generics in go, I refactored this package such that you could explicitly set the types of the key and value when instantiating the cache.  I found it difficult to run go2 code locally hence this blogpost.

### Dependencies

- Docker 

### Approach

Luckily, there's a docker image with the `go2go` tool already installed ([levonet/golang:go2go](https://hub.docker.com/r/levonet/golang)). The idea here is to build/run/test the go2 code inside this docker container. 

#### Build

Write your go2 code in a file ending in `.go2` e.g cache.go2. From the directory where the file is located, run the command below to build the it

```bash
docker run --rm -v "$PWD":/go/src/myapp -w /go/src/myapp levonet/golang:go2go go tool go2go build
```

### Run

Similarly, you can run your code using the command 

```bash
docker run --rm -v "$PWD":/go/src/myapp -w /go/src/myapp levonet/golang:go2go go tool go2go run
```

### Test

You could also test using the command 

``` bash
docker run --rm -v "$PWD":/go/src/myapp -w /go/src/myapp levonet/golang:go2go go tool go2go test
```

### Creavats

- The [go2go command doesn't support go modules](https://github.com/golang/go/issues/40061). I had to work around this by creating a custom docker file with steps to download my dependencies manually.
- I can't get test coverage using the go2go test tool. It can do the tests but since it translates the go code inside the same file as the `_test.go` file. I couldn't get test coverage for files in this directory.


### Workarounds

- I solved the go.mod problem by creating a custom Dockerfile which downloads my dependencies and adds them to the `go2go build path`

```Dockerfile
FROM levonet/golang:go2go

## "apt-get update" updates package list
## "apt-get install git -y" installs 'git' the "-y" flag is there to answer yes to all prompts
RUN apt-get update && apt-get install git -y

# This command clones the dependencies in my GOPATH
RUN git clone https://github.com/dgrijalva/lfu-go /go/src/github.com/dgrijalva/lfu-go && \
    git clone https://github.com/arschles/assert /go/src/github.com/arschles/assert

# This command copies all my files in the directory /go/src/myapp in the container
COPY ./ /go/src/myapp

## This changes the working directory
WORKDIR /go/src/myapp
```

- Build the docker image using the command below the `-t cache` is to tag the image as `cache`

```
docker build . -t cache
```

- You can now build/run/test the `.go2` code using the commands below

```bash
# Test
docker run --rm lfucache go tool go2go test

# Build
docker run --rm lfucache go tool go2go build

# Run
docker run --rm lfucache go tool go2go run
```

This can also be done with a CI/CD tool like travis. I have the following travis file the [`lfucache`](https://pkg.go.dev/github.com/NdoleStudio/lfu-cache?tab=doc) package

```yml
services:
  - docker

before_install:
  # This builds the docker file containing the tests
  - docker build . -t lfucache

script:
  # This tests the go2 files
  - docker run --rm lfucache go tool go2go test
```