Developing in Go on Windows Subsystem for Linux (WSL)

Nate Carpenter
5 min readMar 13, 2021

Getting the Best of Both Worlds

I’m a software architect, which means I don’t get nearly as many chances to write code as I want. And, just about every time I do, I end up fooling around getting my development environment back up to snuff, which takes almost as much time as cranking out the code itself.

My team is doing a lot of Golang development, and I’m quite happy with the language as it takes me back to my C/C++ roots (X/Motif!).

But, we’re issued Windows laptops, and coding directly under Windows (while MILES better than it used to be) still leads to some impedances. But Microsoft has made it possible to drop a Linux distribution right into Windows 10, which gives me all the power of the Penguin while still getting to run my other IDEs (PowerPoint and Visio) like a good architect.

So, on this slow Saturday morning I decided to create a clean development environment on my PC using Windows Subsystem for Linux (WSL2, to be precise) with the goal of getting a nice, clean, Linux-based Go setup that supports Visual Studio Code running out of WSL2.

Step 1: Get Linux from Microsoft

Never thought I’d write that line.

One caveat: I’m using a limited user account on Windows 10 because I like not accidentally installing malware. This causes no end of annoyance but it’s worth it. For this all to work you will still need the password to get elevated privileges for the machine.

Surprisingly, getting Linux distros from Redmond is pretty simple, and just involves following Microsoft’s instructions for installing WSL2. I’m using Ubuntu.

Linux distributions on the Windows Store
“Linux is a cancer” — Steve Ballmer. He wasn’t wrong apparently.

I highly advise installing Windows Terminal as well, as recommended in the article. It makes it much easier to keep lots of terminals open — not just bash but PowerShell and (ick) Command Prompt.

Once installed, you’ll need to mess with the Settings in Windows Terminal if you want the Ubuntu shell to be your default. You will want to make sure this line is in your Ubuntu profile in Windows Terminal’s settings.jsonwith your Linux username, which will make sure your terminal opens in the Linux home directory instead of your Windows home directory.

“startingDirectory”: “\\\\wsl$\\Ubuntu\\home\\<your Linux name>”

Step 2: Housekeeping and Gitting Git

Great, now we have Linux on Windows. It might be a bit out of date depending on when you’re doing this, so ensure you do this (and get a cup of coffee, it can take a minute):

$ sudo apt update;sudo apt upgrade -y

Git is an essential tool for any modern developer, but you knew that. You may already have it installed on Windows, but WSL can’t get to that instance. Microsoft also has good instructions for setting up Git, but depending on the distro you chose, it’s probably already installed. Short version:

$ sudo apt install git

Step 3: Let’s Avoid File System Fights

You’ll soon realize that your WSL and Windows file systems are not the same, and that they kind of hate each other, and both will take it out on you for trying to use the other. The main point of contention is that your username and home directory are both different depending on whether you’re in Windows or WSL!

  • Windows Home (from Windows): C:\Users\<your Windows name>
  • Windows Home (from WSL): /mnt/c/users/<your Windows name>
  • WSL Home (from Windows): \\wsl$\Ubuntu\home\<your Linux name>
  • WSL Home (from WSL): /home/<your Linux name> (or just ~)

This comes to the forefront when downloading something when downloading something from a browser, which gets put in C:\Users\<your Windows name>\Downloads . So let’s make a symbolic link. This will keep your downloads in one place. Here’s what I did:

$ sudo ln -s /mnt/c/Users/<your Windows name>/Downloads ~/Downloads

Now we have a directory in our Linux home that is really a link to our Windows Downloads directory. This will come in useful, trust me.

Another big thing, and I’d make this flash and spin Geocities-style if I could:

NEVER PUT YOUR CODE IN THE WINDOWS FILESYSTEM

NEVER DO FILE INTENSIVE STUFF ACROSS FILESYSTEMS

Why? Because really WSL is running in a virtual machine with its own filesystem, and so if you (say) try to unzip a big file, or download a ton of NPM packages, or run a build when your source is on one system and your destination is on another, you’re gonna wait. A long time. So don’t do it.

You’ll also eventually run into line endings issues if you try to work out of Windows and Linux on one code base. These are a near-infinite time sink. Let’s avoid them by staying in WSL as much as possible.

To do this I just make a directory ~/projects in WSL and use that for all my code.

A super useful trick — you can do the following in WSL!

$ explorer.exe .

You’re welcome.

Step 4: Go Get Go!

All right, we’re ready to get our language environment set up. Finally.

At the time of this writing, there are emerging new ways to do this install, but we’re going old-school to stay consistent. Download the Linux go distro from here. Hey, it’s in your ~/Downloads directory! See why that’s nice? Now just follow the instructions on that post-download page. For me that involved running these commands:

$ sudo rm -rf /usr/local/go$ sudo tar -C /usr/local -xzf ~/Downloads/go1.17.3.linux-amd64.tar.gz

Then I set my paths as directed in the instructions. This is also a good time to set any other Go environment variables, especially if you’re working with private repos (GOPRIVATE and GOSUMDB in particular) I put this in my ~/.profile (you’ll then need to source ~/.profile to pick up the change):

# set PATH and environment for go if it exists
if [ -d "/usr/local/go" ] ; then
export GOPATH=$HOME/go
export GOBIN=$GOPATH/bin
PATH="$GOBIN:/usr/local/go/bin:$PATH"
export GOPROXY=https://proxy.golang.org,direct
fi

Note — if you are in China, your proxy will need to be https://goproxy.io instead.

OK, you’re good to Go!

Step 5: Can We VSCode Already?

Yes.

If you haven’t already, install VSCode on Windows. Why not in WSL? Because magic. Just wait. Now, go to your WSL console and type in:

$ code .

Give it a second, and VSCode should appear. Then, it’ll pop up a little window like this:

Dialog to install WSL extension

Go ahead and hit Install. (Note — if you don’t see this, then you need to manually install the VSCode Remote Development extensions)

Now, and this is important, exit VSCode and (again) in your WSL console type:

$ code .

Ubuntu will then install the VS Code Server which does some magical stuff I don’t need to understand to use it. It’ll keep your extensions synched when running out of Windows or out of WSL too. You’re in business!

Next Steps

This should get you to the baseline you need to start coding in Go on WSL. There are a bunch of things you’ll probably end up doing, like:

  • Customizing your .bashrc and .profile files to do all the auto-completes for Git and other things
  • Customizing Windows Terminal to your color likings (I need to do this because the default scheme isn’t colorblind-friendly)
  • Setting up your Git environment, your repo credentials, and such

Hope this was a helpful recipe to get going; enjoy and stay safe!

--

--

Nate Carpenter

If it's optional, why do I get prompted every time?