Fatih Arslan

My thoughts about Programming, Coffee, Bags and various other stuff

Why you should use a Go module proxy

After the introduction of Go modules, I thought everything I need to know was finalized. I quickly realized this wasn’t the case. Recently, people started to advocate using a Go module proxy. After researching the pros and cons, I’ve concluded that this is one of the most important changes in recent years. But why is that the case? What makes Go module proxy so special?

In Go modules, if you add a new dependency or build your Go module on a machine with clean cache, it’ll (go get) download all the dependencies based on go.mod and will cache it for further operations. You can bypass the cache (and with that downloading dependencies) by using a vendor/ folder and constructing go use this folder with the -mod=vendor flag.

But both of these approaches are not perfect and we can do better.

Problems of (not) using the vendor/ folder

Here are some disadvantages if you use the vendor/ folder:

What if you skip the vendor/ folder? This also doesn’t help because now you’re dealing with these issues:

How can we improve this situation?

Advantages of using a Go module proxy

By default the go command downloads modules from VCS’s directly. The GOPROXY environment variable allows further control over the download source. The environment variable configures the go command to use a Go module proxy.

By setting the GOPROXY environment variable to a Go module proxy, you can overcome all of the disadvantages listed above:

As you see, using a Go module proxy is a win for everyone. But how do we use it? What if you don’t want to maintain your own Go module proxy? Let us look into many alternative options.

How to use a Go module proxy

To start using a Go module proxy, we need to set the GOPROXY environment variable to a compatible Go module proxy. There are multiple ways:

1.) If GOPROXY is unset, empty or set to direct then go get will use a direct connection to the VCS (e.g github.com):

GOPROXY=""
GOPROXY=direct

It can be also set to off, which means no network use is allowed.

GOPROXY=off

2.) You can start using a public Go proxy. One of your options is to use the Go proxy from the Go team (which is run by Google). More information can be found here: https://proxy.golang.org/

To start using it, all you have is to set the environment variable:

GOPROXY=https://proxy.golang.org

Other public proxies are:

GOPROXY=https://goproxy.io
GOPROXY=https://goproxy.cn # proxy.golang.org is blocked in China, this proxy is not

3.) You can run several open source implementations and host it yourself. Some of these are:

You need to maintain these yourself. It’s up to you if you want to serve it over the public internet or on your internal network.

4.) You can buy a commercial offering:

5.) You can pass a file:/// URL. Because a Go module proxy is a web server that responds to GET requests (with no query parameters), a folder in any filesystem can be also used to serve as a Go module proxy.

Upcoming Go v1.13 changes

There will be some changes regarding Go proxy in the Go v1.13 version which I think should be highlighted:

  1. the GOPROXY environment variable may now set to comma-separated list. It’ll try the first proxy before falling back to the next path.
  2. The default value of GOPROXY will be https://proxy.golang.org,direct. Anything after the direct token is ignored. This also means that go get will now by default use GOPROXY. If you don’t want to use Go proxy at all, you need to set it to off.
  3. A new GOPRIVATE environment variable is introduced, that contains a comma-separated list of glob patterns. This can be used to bypass the GOPROXY proxy for certain paths, especially private modules in your company (e.g: GOPRIVATE=*.internal.company.com).

All of these changes indicate how the Go module proxy is a central and important part of Go modules.

Verdict

Using GOPROXY both via public and private networks has a lot of advantages. It’s a great feature that works seamlessly with the go command. Giving the fact that it has so many advantages (secure, fast, storage efficient) it would be wise to embrace it quickly for your projects or in your organization. Also, with Go v1.13, it’ll be enabled by default, which is another welcoming step improving the state of dependency management in Go.


If you have any questions or feedback, please feel free to share it with me on Twitter: @fatih