Golang: configuring useful user snippets in VSCode

VSCode is my favorite IDE nowadays: simple, lightweight and versatile.

In this article I’ll show how we can configure some useful user snippets in VSCode to make our life easier.

Table driven tests snippet

Since I read this Dave Cheney’s article, table driven tests has become my favorite way for writing tests in Golang.

Here’s an example for calculating Fibonnaci number:

func TestRecursiveFibonacci(t *testing.T) {
    testCases := []struct {
        name string
        n    uint
        want uint
    }{
        {
            name: "zero",
            n:    0,
            want: 0,
        },
        {
            name: "one",
            n:    1,
            want: 1,
        },
        {
            name: "two",
            n:    2,
            want: 1,
        },
        {
            name: "three",
            n:    3,
            want: 2,
        },
    }
    for _, tc := range testCases {
        t.Run(tc.name, func(t *testing.T) {
            if got := RecursiveFibonacci(tc.n); got != tc.want {
                t.Errorf("got: %d, want: %d", got, tc.want)
            }
        })
    }
}

This is the output:


=== RUN   TestRecursiveFibonacci
=== RUN   TestRecursiveFibonacci/zero
=== RUN   TestRecursiveFibonacci/one
=== RUN   TestRecursiveFibonacci/two
=== RUN   TestRecursiveFibonacci/three
--- PASS: TestRecursiveFibonacci (0.00s)
    --- PASS: TestRecursiveFibonacci/zero (0.00s)
    --- PASS: TestRecursiveFibonacci/one (0.00s)
    --- PASS: TestRecursiveFibonacci/two (0.00s)
    --- PASS: TestRecursiveFibonacci/three (0.00s)
PASS
ok      bitbucket.org/tiagoharris/fibonacci/fibo    0.715s

It can be a bit boring writing this test structure everytime. That’s where a predefined user snippets comes to help.

Configuring a user code snippet in VSCode

Open up VSCode. If you’re using macOS, hit command + shift + p and start typing “snippet”:

No alt text provided for this image

After pressing ENTER, type “go” and select “go.json”:

No alt text provided for this image

Then, ENTER again and it will open “go.json”:

No alt text provided for this image

Here’s where we’ll define a snippet for generating the table driven test basic structure:

"Table driven test": {
        "prefix": "tabletest",
        "body": [
          "func Test${1:YourFunc}(t *testing.T) {",
          "\ttestCases := []struct{",
          "\t\tname string",
          "\t}{",
          "\t\t{",
          "\t\t\tname: \"happy path\",",
          "\t\t},",
          "\t}",
          "\tfor _, tc := range testCases {",
          "\t\tt.Run(tc.name, func(t *testing.T) {",
          "\t\t})",
          "\t}",
          "}"
        ],
        "description": "Create basic structure for a table driven test"
 }
  • “Table driven test”: a descritive name for our snippet;
  • “prefix”: how can we invoke this snippet. In our case, everytime we type “tabletest” in any golang file (*.go), the structure will be written into it;
  • “body”: the snippet itself. I’m using ‘\t’ for tabbing. If you want to enter a new line, just type in ‘\n’;
  • “func Test${1:YourFunc}(t *testing.T) {“: here I’m using “${1:YourFunc}” so the cursor will be positioned around “YourFunc”;
  • “description”: a friendly description about this snippet.

Invoking it

No alt text provided for this image

When start typing “table”, VSCode will suggest our snippet. Press ENTER:

No alt text provided for this image

Notice that the cursor is around “YourFunc”, so you can type your test name right away.

Main function snippet

Here’s another snippet that I find useful: it defines a basic structure for a file with a main function:

"Main Func": {
        "prefix": "mf",
        "body": [
          "package main\n",
          "import (",
          "\t\"fmt\"",
          "\t\"os\"",
          ")\n",
          "func run() error {",
          "\treturn nil",
          "}\n",
          "func main() {",
          "\tif err := run(); err != nil {",
          "\t\tfmt.Println(err)",
          "\t\tos.Exit(1)",
          "\t}",
          "}",
        ],
        "description": "Create basic structure for a script with main function"
}

Invoking it

No alt text provided for this image

Press “ENTER”:

No alt text provided for this image

Then a basic structure for a file with a main function will be written.

Our final “go.json” is the following:

{
    "Table driven test": {
        "prefix": "tabletest",
        "body": [
          "func Test${1:YourFunc}(t *testing.T) {",
          "\ttestCases := []struct{",
          "\t\tname string",
          "\t}{",
          "\t\t{",
          "\t\t\tname: \"happy path\",",
          "\t\t},",
          "\t}",
          "\tfor _, tc := range testCases {",
          "\t\tt.Run(tc.name, func(t *testing.T) {",
          "\t\t})",
          "\t}",
          "}"
        ],
        "description": "Create basic structure for a table driven test"
    },
    "Main Func": {
        "prefix": "mf",
        "body": [
          "package main\n",
          "import (",
          "\t\"fmt\"",
          "\t\"os\"",
          ")\n",
          "func run() error {",
          "\treturn nil",
          "}\n",
          "func main() {",
          "\tif err := run(); err != nil {",
          "\t\tfmt.Println(err)",
          "\t\tos.Exit(1)",
          "\t}",
          "}",
        ],
        "description": "Create basic structure for a script with main function"
    }
}

Cool, isn’t it?