Skip to content

nikolaydubina/go-recipes

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🦩 Go Recipes

Handy well-known and lesser-known tools for Go projects

Know some cool tool or one-liner? Have a feature request or an idea?
Feel free to edit this page or create an Issue!

Hits go-recipes

Contents

AI tools

Advanced autocompletion with Copilot

Start typing and after few seconds you will get autocompletion suggestion. Some useful ways to interact with it listed bellow.

given a function signature and docstring, it will suggest function body
given a function body, it will suggest docstring

Requirements

VSCode
GitHub account

Pull requests recommendations with CopilotX

CopilotX has dedicated solutions for: writing PR description; writing tests; writing PR reviews and replies; applying requested PR changes. As of 2023-06-04, it is on waitlist. documentation.

Code analysis and recommendations with charmbracelet/mods

This is a nice looking CLI wrapper for major LLM APIs from Charm team. It supports OpenAI and LocalAI. It passes arbitrary human language command string and concatenated with STDIN input. Multiple useful commands are possible.

mods -f "what are your thoughts on improving this code?" < main.go | glow
mods -f "you are an expert Go programmer. find potential bugs in following Go code." < my_class.go | glow

Requirements

# OpenAI token or LocalAI model and server
go install github.com/charmbracelet/glow@latest
go install github.com/charmbracelet/mods@latest

Pull request recommendations with gpt-pullrequest-updater

This tool generates GitHub pull request description and review using OpenAI ChatGPT. There is also GitHub Action available. — @ravilushqa

Requirements

# OpenAI token
# GitHub token
go install github.com/ravilushqa/gpt-pullrequest-updater/cmd/description@latest
go install github.com/ravilushqa/gpt-pullrequest-updater/cmd/review@latest

Commit message recommendation

Short summaries of changes usually work well.

git diff | mods "summarize following git diff into short git commit message."
git diff | mods "you are expert Go programmer. you are owner of this codebase. think through step by step. summarize following git diff into short git commit message under 10 words."

Example

Add new entries for Using AI in Go projects, including Advanced autocompletion with Copilot and Code analysis and recommendations with charmbracelet/mod. Update page.yaml accordingly.

Requirements

# OpenAI token or LocalAI model and server
go install github.com/charmbracelet/mods@latest

Test case recommendation

Concatenate two files and ask to recommend missing test cases. It is not precise, has high false positive and high false negative rate. Often can not detect that tests cases are present at all. However, it can give a fresh perspective on your code. Best results are produced when asking succinct short replies. Example outputs bellow.

cat fpdecimal.go fpdecimal_test.go | head -c 3600 | mods -f "you are an expert Go programmer. investigate supplied Go program and associated test suite. think through this step by step. make sure you get the right answer. recommend missing test cases. write very succinctly. under 100 words." | glow
cat fpdecimal.go fpdecimal_test.go | head -c 4000 | mods -f "investigate supplied Go program and associated test suite. recommend missing test cases." | glow

Example

For additional test cases, consider adding tests for negative float values, positive and negative infinity, unsigned
integers, zero divided by a number greater than zero, and division with only zeros.                       
------------------
  Test cases:                                                                                                                                                                                                                             
  • Test for unmarshalling JSON into Decimal                                                                          
  • Test for marshalling Decimal to JSON                                                                              
  • Test for multiplication with zero                                                                                 
  • Test for multiplication identity                                                                                  
  • Test for division with zero                                                                                       
  • Test for all comparison operations for the Decimal struct.                                                        
------------------
Missing test cases for the  fpdecimal  Go program include those for testing the  DivMod  and  FromString  functions.
Additionally, there should be tests checking that zero division is not allowed, and tests that ensure the           
FractionDigits  value does not change during the program's runtime. Important test cases include comparing decimals 
for equality, as well as testing the commutativity, associativity, and identity properties of addition and          
multiplication. Finally, the program should have a test that verifies the  MarshalJSON  and  UnmarshalJSON          
functions.

Time complexity estimate

This is one of recommended use cases by OpenAI website. It can produce fairly good estimations. However, in its direct form usefulness is questionable, since complex cases are not handled precisely enough, educational potential is limited, and simple cases do not require this. Perhaps, this will be utilized in future work on using models in compiler and programming. Copy function and pipe it to model with prompt asking for time complexity estimation. Bellow is an example.

pbpaste | mods -f "calculate time complexity of following Go code function." | glow
func AppendFixedPointDecimal(b []byte, v int64, p int) []byte {
  if v == 0 {
    return append(b, '0')
  }

  if p == 0 {
    return strconv.AppendInt(b, v, 10)
  }

  if v < 0 {
    v = -v
    b = append(b, '-')
  }

  s := len(b)
  b = strconv.AppendInt(b, v, 10)

  if len(b)-s > p {
    i := len(b) - p
    b = append(b, 0)
    copy(b[i+1:], b[i:])
    b[i] = '.'
  } else {
    i := 2 + p - (len(b) - s)
    for j := 0; j < i; j++ {
      b = append(b, 0)
    }
    copy(b[s+i:], b[s:])
    copy(b[s:], []byte(zeroPrefix[:i]))
  }

  return b
}

Example

The time complexity of the AppendFixedPointDecimal function is O(N), where N is the length of the input byte slice  
b. This is because the function performs a constant number of operations for each byte in b, and the largest        
operation within the function is the loop that appends zeros to the byte slice, which has a length proportional to  
the input. Other operations, such as integer conversions and comparisons, are considered constant time since the    
input size is fixed.                 
------------------
The time complexity of the function depends on the input values  v  and  p .    
• The first three if statements before the main computation take constant time, 
so they don't contribute to the overall time complexity.                        
• The  strconv.AppendInt  function used twice has a time complexity of          
O(log(v)), where v is the integer being converted to a string representation in 
base 10.                                                                        
• The condition  len(b)-s > p  has a constant time complexity.                  
• The  append  and  copy  operations inside the if and else blocks take linear  
time proportional to  p .                                                       
• The  for  loop has a constant number of iterations, specifically 2 +  p  - (  
len(b)-s ). The  append  and  copy  operations inside the loop also take linear 
time proportional to  p .                                                       
Therefore, the overall time complexity of the function is O(log(v) + p).

Testing

Make treemap of coverage with go-cover-treemap

Visualize distribution of code coverage in your project. This helps to identify code areas with high and low coverage. Useful when you have large project with lots of files and packages. This 2D "image-hash" of your project should be more representative than a single number. Also available at https://go-cover-treemap.io. — @nikolaydubina

go test -coverprofile cover.out ./...
go-cover-treemap -coverprofile cover.out > out.svg

Requirements

go install github.com/nikolaydubina/go-cover-treemap@latest

Browse coverage

This is very helpful tool from the official Go toolchain. Similar visualization is integrated into VSCode and Goland, but can be used separately.

go test -coverprofile cover.out ./...
go tool cover -html=cover.out

Browse coverage with gocov-html

Browse code coverage in statically generated HTML page. Multiple styles are supported. You may need to convert coverage report into gocov format. — @matm

gocov test strings | gocov-html -t golang > strings.html
gocov test encoding/csv strings | gocov-html -t kit > strings.html
gocov test strings|./gocov-html -cmax 90 > strings.html # show functions with <90% coverage

Requirements

go install github.com/axw/gocov/gocov@latest
go install github.com/matm/gocov-html/cmd/gocov-html@latest

Browse coverage in terminal with gocovsh

Browse code coverage similarly to HTML provided by official Go toolchain, but in terminal. Other notable features are package level statistics, coverage only for changed files. — @orlangure

go test -cover -coverprofile coverage.out
gocovsh                        # show all files from coverage report
git diff --name-only | gocovsh # only show changed files
git diff | gocovsh             # show coverage on top of current diff
gocovsh --profile profile.out  # for other coverage profile names

Requirements

go install github.com/orlangure/gocovsh@latest

Pretty print coverage in terminal with nikandfor/cover

It is similar to go tool cover -html=cover.out but in terminal. You can filter by functions, packages, minimum coverage, and more. — @nikandfor

cover

Requirements

go install github.com/nikandfor/cover@latest

Run coverage collector server with goc

This tool allows to collect coverage as soon as code is executed. — @qiniu

goc server
goc build
goc profile

Requirements

go install github.com/qiniu/goc@latest

Visualize live coverage in VSCode with goc

Official Go VSCode plugin already has coverage highlighting. In addition to that, this tool shows covered lines as soon as they are executed. This can be useful for running manual integration or system tests or debugging. — @qiniu

Requirements

go install github.com/qiniu/goc@latest

🎊 Shuffle tests

This is less known option that is disabled by default. However, for robust test suite it is beneficial. More test flags and full description is available at go help testflag.

go test -shuffle=on

Run tests sequentially

Use when you need to synchronize tests, for example in integration tests that share environment. Official documentation.

go test -p 1 -parallel 1 ./...

Run tests in parallel

Add t.Parallel to your tests case function bodies. As per documentation, by default -p=GOMAXPROCS and -parallel=GOMAXPROCS when you run go test. Different packages by default run in parallel, and tests within package can be enforced to run in parallel too. Make sure to copy test case data to new variable, why explained here. Official documentation.

...
for _, tc := range tests {
    tc := tc
    t.Run(tc.name, func(t *testing.T) {
        t.Parallel()
        ...

Detect goroutine leaks with goleak

Instrument your test cases with verification call. Alternatively, you can add single call in TestMain. This tool was recommended by Pyroscope in blog. — Uber

func TestA(t *testing.T) {
  defer goleak.VerifyNone(t)
  ...
}

Requirements

go get -u go.uber.org/goleak

Detect goroutine leaks with leaktest

Refactored, tested variant of the goroutine leak detector found in both net/http tests and the cockroachdb source tree. You have to call this library in your tests. — @fortytw2

func TestPoolContext(t *testing.T) {
  ctx, cancel := context.WithTimeout(context.Background(), time.Second)
  defer cancel()
  defer leaktest.CheckContext(ctx, t)()

  go func() {
    for {
      time.Sleep(time.Second)
    }
  }()
}

Summarize go test with tparse

This lightweight wrapper around STDOUT of JSON of go test will nicely render colorized test status, details of failures, duration, coverage, and package summary. — @mfridman

set -o pipefail && go test ./... -json | tparse -all

Requirements

go install github.com/mfridman/tparse@latest

Decorate go test with richgo

Add colors and enrich go test output. It can be used in CI pipeline and has lots of alternative visualizations and options. — @kyoh86

richgo test ./...

Requirements

go install github.com/kyoh86/richgo@latest

Decorate go test with gotest

Add colors to go test output. Very lightweight wrapper around go test STDOUT. — @rakyll

gotest ./...

Requirements

go install github.com/rakyll/gotest@latest

Decorate go test with gotestsum

This wrapper around go test renders test output in easy to read format. Also supports JUnit, JSON output, skipping slow tests, running custom binary. — @dnephin

gotestsum --format dots

Requirements

go install gotest.tools/gotestsum@latest

Format go test results as documentation with gotestdox

Decorates go test results by converting CamelCaseTestNames into readable sentences. — @bitfield

gotestdox ./...

Requirements

go install github.com/bitfield/gotestdox/cmd/gotestdox@latest

Get slowest tests with gotestsum

This is subcommand of gotestsum that processes JSON output of go test to find slowest tests. — @dnephin

go test -json -short ./... | gotestsum tool slowest --threshold 500ms

Example

gotest.tools/example TestSomething 1.34s
gotest.tools/example TestSomethingElse 810ms

Requirements

go install gotest.tools/gotestsum@latest

Auto-Instrument skipping slowest tests with gotestsum

This is subcommand of gotestsum that processes JSON output of go test to find slowest tests and instruments test cases to skip them with t.Skip() statements. — @dnephin

go test -json ./... | gotestsum tool slowest --skip-stmt "testing.Short" --threshold 200ms

Example

gotest.tools/example TestSomething 1.34s
gotest.tools/example TestSomethingElse 810ms

Requirements

go install gotest.tools/gotestsum@latest

Automatically re-run failed tests with gotestsum

Other useful option of gotestsum is to re-run failed tests. For example, if you have flaky tests that are idempotent, then re-running them may be a quick fix. — @dnephin

gotestsum --rerun-fails --packages="./..."

Requirements

go install gotest.tools/gotestsum@latest

Make JSUnit test report with gotestsum

JUnit is widely used format for test reporting. — @dnephin

go test -json ./... | gotestsum --junitfile unit-tests.xml

Requirements

go install gotest.tools/gotestsum@latest

Make JSUnit test report with go-junit-report

JUnit is widely used format for test reporting. Go benchmark output is also supported. — @jstemmer

go test -v 2>&1 ./... | go-junit-report -set-exit-code > report.xml

Requirements

go install github.com/jstemmer/go-junit-report/v2@latest

Get packages without tests

If code coverage does not report packages without tests. For example for CI or quality control.

go list -json ./... | jq -rc 'select((.TestGoFiles | length)==0) | .ImportPath'

Example

github.com/gin-gonic/gin/ginS
github.com/gin-gonic/gin/internal/json

Requirements

https://stedolan.github.io/jq/download/

Perform Mutation Testing with ooze

Mutation testing is a technique used to assess the quality and coverage of test suites. It involves introducing controlled changes to the code base, simulating common programming mistakes. These changes are, then, put to test against the test suites. A failing test suite is a good sign. It indicates that the tests are identifying mutations in the code—it "killed the mutant". If all tests pass, we have a surviving mutant. This highlights an area with weak coverage. It is an opportunity for improvement. — @gtramontina

go test -v -tags=mutation

Requirements

go get github.com/gtramontina/ooze

Perform Mutation Testing with avito-tech/go-mutesting

This is fork of zimmski/go-mutesting. It has more mutators and latest updates. — @vasiliyyudin

go-mutesting ./...
for _, d := range opts.Mutator.DisableMutators {
  pattern := strings.HasSuffix(d, "*")

-	if (pattern && strings.HasPrefix(name, d[:len(d)-2])) || (!pattern && name == d) {
+	if (pattern && strings.HasPrefix(name, d[:len(d)-2])) || false {
    continue MUTATOR
  }
}

Requirements

go install github.com/avito-tech/go-mutesting/cmd/go-mutesting@latest

Perform Mutation Testing with go-mutesting

Find common bugs source code that would pass tests. This is earliest tool for mutation testing in Go. More functions and permutations were added in other mutation Go tools it inspired. — @zimmski