I had a wonderful time at GopherCon 2017. One of the highlights was being a mentor at the Go Contributor Workshop. This involved two 1.5-hour sessions where Go developers of all skill levels were walked through the process of making their first contributions to the Go project. Every table at the session had two or more mentors to help. Mentors included members of the Go team and community members familiar with the process.
Any contribution to open source can be intimidating, but a large project like Go even more so. Then there’s Gerrit (the code review tool used by Go) and the Contributor License Agreement (CLA) to contend with. While there are reasons for these complications, I don’t think anyone would claim the process is as easy as it should be. The workshop was a great step to getting more people involved in the project. Big shout out to Steve Francia, Jessie Frazelle, and everyone else involved in making it happen!
Now to the meat of this article. During the workshop contributors were encouraged to write a new example for standard library functions. Go examples can be written to be testable, and if you’re going to write a new test, it’s probably a good idea to run that test before submitting to Gerrit.
This can present a problem. Normally, running tests involves running
go test [package], which executes the tests with the version of Go currently installed. In most cases this is what you would want, and it will work for some standard library packages, but sometimes it will present confusing error messages.
$ cd ~/golang/src/go/types
$ go test
api_test.go:14:2: use of internal package not allowed
FAIL _/Users/kale/golang/src/go/types [setup failed]
In the example above, one of the test files imports
go resolves to my default 1.8 install the toolchain attempts to import that package from
[Go 1.8 install]/src/internal/testenv. This is not allowed because internal packages can only be imported if they share a common root directory.
I could try setting
GOROOT to match the development checkout of Go.
$ GOROOT="$HOME/golang" go test -v
go: open /Users/kale/golang/src/runtime/internal/sys/zversion.go: no such file or directory
Now there’s a different error, this one is because
zversion.go is generated when the toolchain is built and embeds the Go version in the binary.
We could probably hack our way around this too, and we might be able to get this working in packages with simpler dependencies, but there are a number of other mismatches that may come up. So let’s do it the right way.
The Right Way
What we really want to do is run the tests with a version of the Go toolchain built from the source we’re working on.
# Path that the Go repo was cloned to.
$ GODEV=$HOME/golang# Move into the src directory.
$ cd $GODEV/src# Set the bootstrap Go install to the current installation.
$ GOROOT_BOOTSTRAP=$(go env GOROOT) ./make.bash
[output omitted]# Use the newly built toolchain to run the test.
$ $GODEV/bin/go test -v go/types
=== RUN ExampleInfo
--- PASS: ExampleInfo (0.00s)
ok go/types 7.129s
In this case we didn’t have to set
GOROOT at all. When the toolchain is built the build location will become the default
Note: If you have
GOROOT set already, you will need to change it or unset it for this to work.
Building the toolchain can take a couple minutes.
make.bash builds, but does not run all the tests.
all.bash builds and runs tests, which will take much longer.
Note: For Windows there are
The toolchain doesn’t need to be rebuilt every time a change is made unless you’re modifying and testing the toolchain itself.
Based on my observations at the workshop, I opened https://golang.org/issue/21037 to at least make the build process a little easier by removing the need to explicitly set
PS: Thanks to Steven Klassen for proof reading this post.
GopherAcademy - Conferences, Training, and Community
Contributing to the Go project Contributing to the Go project can seem overwhelming, especially at first. The official…