Skip to main content
In this course we will work in a Go Bazel repository. Clone the Go starter template to follow along.

Application code

Let’s start by creating a program we can run. In Go, there is a convention of placing these in a cmd folder. Let’s create cmd/hello/main.go with this basic content:

Running the go tool

To ensure we’re using the Bazel-managed version of the Go SDK rather than something you might happen to have installed on your computer, we replace go commands with the executable @rules_go//go target that comes from rules_go. To make this even easier to discover, our repository has this aliased at ./tools/go. Under the covers, you can see that script is just running the rules_go target, and then ensuring the correct working directory. If you prefer, you could alias the go command in your terminal to run this script instead, so you don’t need to remember to run the correct one.

External dependencies

As you can see, our application uses the cowsay third-party library. We’ll need to add this to our go.mod file like we would in any Go project. We could use the go get command, but this installs the library to a system location which differs from how Bazel manages dependencies. So instead we’ll use the mod tidy command:
This results in updating the go.mod file, which is how Go provides for reproducible builds. If you open that file, you should see this line was added for you. (The version may differ of course, since our Go source file didn’t specify any constraint).
For supply-chain security, we might be suspicious that the maintainers of this library could accidentally allow an attacker to re-tag this v1.0.2 and point it to malicious code. The go.sum file provides the cryptographic hash of the library at the time we ran go mod tidy, following the “Trust on First Use” principle. Additionally, rules_go exposes an external repository where this library is built from sources. Thanks to the strict visibility feature of bzlmod, this dependency must be declared in MODULE.bazel. Looking in that file, you’ll see this line was also added for you:
That’s it! We’ve got this library ready to use as a dependency of our app.
If you used earlier versions of Go with Bazel, you will notice this is significantly simpler to set up! Now that the go.mod file is read directly, you no longer need go_repository rules.

Generate BUILD files

Next we need a go_binary target to make our application runnable. As we learned in the 101 course, we can use the gazelle command:
Now look inside the cmd/hello/BUILD.bazel file. You’ll see something like the following has been automatically added for you:
Aspect CLI provides the configure command. If you are in a project using vanilla Bazel, you’ll have to follow the gazelle setup instructions, and build the Gazelle binary from source on each developer’s machine.

Run the application

The bazel run command can be used with a label as a shorthand for “build the application and then spawn the resulting binary”. So we can now run:
The server starts up, and we can navigate to http://localhost:8080/ to see the website it serves.