Golang tips you might not know

haya14busa
4 min readDec 1, 2016

--

This post is for 1st day of [Go Advent Calendar (3)](http://qiita.com/advent-calendar/2016/go3).

I’ll introduce several Golang tips which I guess is not popular but definitely it’s useful at least for me.
Each tips are somewhat small to write one post for them, so I’ll introduce them by this post all at once.

1) gopkgs — List Go packages FAST by using the same implementation as goimports

gopkgs outputs list of Go packages. go list … does the same thing but go list is too slow for daily usage.
On the other hand, gopkgs is fast because it uses same implementation as goimport.
goimport and gopkgs are fast because they take care .goimportignore and include optimization of walking through files under $GOPATH.

gopkgs does just outputting go packages and you might not find it useful, but by using it with filtering tool like https://github.com/peco/peco or https://github.com/junegunn/fzf, it wil helps your Go workflow.

For example, you can move working directory to a package to read implementation, you can find a package you want to open godoc or import by integrating it with your editors.

2) goverage — go test -coverprofile for multiple packages

go test -coverprofile only supports to run one package at once, so we cannot get coverage from multiple packages under the directory. There already existed similar tools or Makefile solution, but the existed tools lack some handling (like -coverpkg arg) and I find it tedious to write Makefile or shell script and combines it with external coverprofile marge tool just to get cover profile. On the other hand, goverage just works simply with one binary and with same options as go test.

The other day, I contributed to https://github.com/mattn/goveralls to support multiple packages and it works well, but I sometimes want to get profile result in html format instead of sending to coverall, so I created goverage.

3) goplay — The Go Playground (https://play.golang.org/) client

When you explain how golang code works to someone, it’s useful to share Go Playground link if the code doesn’t include external dependencies. You can write code in your editor, open playground website, and copy & paste your code but it’s tedious work. goplay is command line tool which runs go code in The Go Playground and generates a shareable link.

If you use Vim, you can pass go code in current buffer to goplay with `:! goplay %` for example.

4) reviewdog — filter lint result by diff

golint helps you write Go-ish code by detecting style mistakes. It’s really useful and we often run golint in CI to make build fail if there are style problems. However, golint sometimes report a problem we don’t have to fix it. Other linter for golang like errcheck also has the same problem. Detecting unchecked errors is really useful but a report contains lots of lines we can just ignore.

reviewdog can filter linter result with diff, so if you run linter with reviewdog, you can find mistakes in new code (git diff) and if there are false positive results, you can just ignore them.

reviewdog both supports to run locally and run in CI service, so you can run lint with reviewdog by git commit hook or in CI service to post results to GitHub.

5) godebug — outputs diff between complex values for tests

Go doesn’t encourage to use assert testing framework. If you want to compare complex values like struct which contains pointer field, slice, map, etc…, you can use reflect.DeepEqual. However, if the values are not same, it’s difficult to report the difference. Just printing got and want value doesn’t work well if values are too large or contains pointer.

Here godebug comes in. github.com/kylelemons/godebug/pretty#Compare prints diff in unified diff format.

Example from godoc:

if diff := pretty.Compare(test.before, test.after); diff != "" {
t.Errorf("%s: post-AddCrew diff: (-got +want)\n%s", test.desc, diff)
}

Output:

add first: post-AddCrew diff: (-got +want)
{
Name: "",
Crew: {
- Galactic President: "Zaphod Beeblebrox",
+ Zaphod Beeblebrox: "Galactic President",
},
Androids: 0,
Stolen: false,
}

It’s really useful to write tests which compare large or complex values casually, and it’s easy to maintain. Internally, godebug converts values to pretty-printed string and compares them by unified-diff. It’s simple and works great!

Wrapping up

I introduced several golang tips which improve Golang workflow. I used them frequently and find them really useful but I guess you might not know some of them. You might also deal with the problems with different ways and if so please share them!

--

--