Local Go Playground

Posted on
go golang docker

The Go playground is an awesome tool for experimentation and education. Like many other Go programmers, it was where I wrote my first Go program. I find myself using it to test the odd code snippet or answer a forum post with some example code every once in a while.

One thing I’ve always wanted the playground to support was my local Go packages. How cool would it be if I could test snippets with code I’ve previously written or downloaded.

Fortunately the playground code is available on Github and comes with a Dockerfile.

A local instance

If you pull the code down and follow the README instructions, you should have a local instance of the playground. I’ve condensed them below.

# clone the repo
git clone https://github.com/golang/playground/ && cd playground
# build the image
docker build -t playground .
# run the image
docker run --rm -d -p 8080:8080 --name playground-container playground

The next two sections explain how you can support custom imports and how you can make your local snippets shareable on the official playground.

Custom imports

If you’ve followed the instructions from the official playground repository, you should be able to augment your docker run command to bind mount your $GOPATH/src directory.

# Replace //d/projects/go/src with your own $GOPATH/src
docker run -v //d/projects/go/src:/go/src --rm -d -p 8080:8080 --name playground-container playground

You should not bind mount your $GOPATH but $GOPATH/src. By doing this you avoid overwriting the $GOPATH/bin directory in the container which holds the playground binary.

Windows users, your GOPATH/src might look like D:\the\path\here\src, you’ll need to format it as //d/the/path/here/src when passing it to the Docker run command.

Sharing

To share your code on the official playground, simply update the handleShare method of the server to make a POST request to https://play.golang.org/share with the form body as the payload.

I updated lines 74 until the end of the share handler with the following code:

// in share.go on line 74 until the end of the function
	resp, err := http.DefaultClient.Post("https://play.golang.org/share", "text/plain", bytes.NewReader(body.Bytes()))
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}

	body.Reset()
	_, err = io.Copy(&body, resp.Body)
	resp.Body.Close()

	fmt.Fprint(w, body.String())

Now when I press share, I get a link formatted like http://localhost:8080/p/HASHHERE in the ‘share’ textbox. Appending the hash onto https://play.golang.org/p/HASHHERE yields the snippet.

You can get a local copy of this source code with the changes already made from my playground fork on Github

I hope you’ve enjoyed this post, if you have any comments feel free to leave one below.

Thanks