The Go Playground: Using Modules
Tags: go, playground, modules
Published: 2023-11-06 07:22:10

This is part of an upcoming series about useful and surprising features of the [Go Playground](https://go.dev/play/). Follow me to read more about the Go Playground!

---

The [Go Playground](https://go.dev/play/) is extremely useful for sharing runnable Go code and testing out standard library functions, but what if you want to test out code that's in an external library? It turns out that the Go Playground can automatically fetch Go modules when you import packages that aren't in the standard library.

Let's check out an example of generating a random UUIDv4 using the [github.com/google/uuid](https://pkg.go.dev/github.com/google/UUID) package:

```go
package main

import (
	"fmt"

	"github.com/google/uuid"
)

func main() {
	u, err := uuid.NewRandom()
	if err != nil {
		panic(err)
	}

	fmt.Println(u)
}
```
{% cta https://go.dev/play/p/w1R-2ig_AcY %}Run{% endcta %}

When we run that code, the Go playground fetches the [github.com/google/uuid](https://pkg.go.dev/github.com/google/UUID) module, then compiles and runs our code. By default, the Go Playground fetches the latest available module version for the specified package. But what if we want to use a different version of the module?

## Major Versions

To fetch a different major version, add a [major version suffix](https://go.dev/ref/mod#major-version-suffixes) to the import path and the Go Playground will fetch that major version instead! For example, to fetch package `mypackage` from version `v2.x.x` of the `github.com/name/example` module, import package
```
github.com/name/example/v2/mypackage
```

Let's check out an example of writing a simple HTTP handler using [v5](https://pkg.go.dev/github.com/go-chi/chi/v5) of the [github.com/go-chi/chi](https://github.com/go-chi/chi) module:

```go
package main

import (
	"fmt"
	"io"
	"net"
	"net/http"
	"os"

	"github.com/go-chi/chi/v5"
	"github.com/go-chi/chi/v5/middleware"
)

func main() {
	r := chi.NewRouter()
	r.Use(middleware.Logger)
	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("hi"))
	})

	listener, err := net.Listen("tcp", ":8080")
	if err != nil {
		panic(err)
	}
	go http.Serve(listener, r)

	fmt.Println("Sending request...")
	res, err := http.Get("http://localhost:8080/")
	if err != nil {
		panic(err)
	}

	fmt.Println("Reading response...")
	if _, err := io.Copy(os.Stdout, res.Body); err != nil {
		panic(err)
	}
}
```
{% cta https://go.dev/play/p/lRZYSapMqOU %}Run{% endcta %}

That example highlights another feature of the Go Playground: **you can run and test local network services, like HTTP servers**! Your code can't access the Internet, but you can run  as many local services as the Go Playground sandbox can handle.

## Any Version

So far we've let the Go Playground fetch the latest version and a specific major version, but we can also specify the exact version of a module if we want. To do that, we'll use another hidden feature of the Go Playground: **you can add multiple source code files**!

In this example, we'll add a `go.mod` file that specifically requests v1.11.7 of the [go.mongodb.org/mongo-driver](https://pkg.go.dev/go.mongodb.org/mongo-driver) module:
```go
package main

import (
	"fmt"

	"go.mongodb.org/mongo-driver/version"
)

func main() {
	fmt.Println(version.Driver)
}
-- go.mod --
module mymodule

require go.mongodb.org/mongo-driver v1.11.6
```
{% cta https://go.dev/play/p/P_nnDYB0zIy %}Run{% endcta %}

That's all for now! In the next Go Playground post, we'll look at displaying images and GIFs in the Go Playground. Subscribe for more!