Go (aka Golang) came to life at Google in 2009. It was designed by several big names:
- Robert Griesemerwho played a major role in the development of the Java Virtual Machine.
- Rob Pike, who holds a US patent for windowed user interface systems, and who helped create the Plan 9 operating system at Bell Labs. (In fact, the mascots for Plan 9 and for Golang are remarkably similar because Pike’s wife, Renée French, is a famous illustrator.)
- Ken Thompsonwho designed and implemented a thing called Unix.
In this article, we will show how easy it is to build a RESTful web service in Go. Next, we’ll show how to deploy this application with Heroku. But before we go on this journey, let’s talk about it briefly why you might want to use Go.
Why go?
To build a web service in 2024, why would you choose Switch over another language, like Python or TypeScript? Go’s biggest advantage over those two languages is speed up. Go is a language that compiles to machine code. It is not interpreted as Python, Ruby, or JavaScript. It’s not even compiled to bytecode and run in a virtual machine like Java. Many benchmarks show that Go is 40x or 50x faster than applications written in interpreted languages. When it comes to speed, Go applications perform similarly to those written in Rust or C++.
Go has a simple syntax, often with only one specific way to do something. This appeals to many developers, especially those who have ever been in a development team environment, where bickering over different ways of doing things eats up valuable time. This simplicity encourages consistency in the code base and offers less confusion about when reading code. (Believe it or not, most developers spend more of their time reading code instead of writing it.)
Go is a young language, so it comes packed with modern features from the nursery. You get automatic garbage collection like in Java or Python. you get built-in linters, formatters and unit testing. You get a rich networking stack in the standard library. And perhaps most useful for network developers: you get easy-to-use multithreading tool called Goroutines.
Yes, there are reasons why not everyone is popular in Goa. One common complaint is about error handling in Go. Functions in Go can return multiple values, one of which is an error code. This is reminiscent of the days of Ca – before the exceptions – and seems admittedly archaic. It’s easy to forget to check error codes for each function. It’s also tedious to filter errors from deep—when you wake up a balrog deep in your application—to somewhere manageable. You know you did it.
Okay, Go cheerleading is over. Let’s go to construction.
Creating a simple RESTful web service in Go
We’ll create a small API service that provides some text operations that applications typically need, such as:
- Encode the given string using a basic Caesar cipher
- Determine if a string is a palindrome
- (Perhaps the most important) SpongeBob – code a snappy response.
If you’d rather jump to the finished code for this app, you can find it in this GitHub repo. We won’t pass main.go
line by line, but we’ll talk about the important parts.
Let’s start with the main function, the code to start the service:
func main()
http.HandleFunc("/is-palindrome", palindromeHandler)
http.HandleFunc("/rot13", rot13Handler)
http.HandleFunc("/spongebob", spongebobHandler)
http.HandleFunc("/health", healthHandler)
appPort := ":" + os.Getenv("PORT")
if appPort == ":"
appPort = ":8080"
err := http.ListenAndServe(appPort, nil)
if err != nil
return
As we mentioned, one of the strong features of Go is expressiveness net/http
standard library. You don’t need any third-party dependencies to get a basic RESTful service up and running quickly. WITH http.HandleFunc
you can easily define your own routes and assign handlers to requests that are directed to those URIs.
The http.ListenAndServe
method starts the server, binding it to the port you specify. When we deploy on Heroku, Heroku will handle setting the PORT var in the environment. For our local implementation, we default 8080
.
Let’s look at the handler:
func spongebobHandler(w http.ResponseWriter, r *http.Request)
decoder := json.NewDecoder(r.Body)
var t requestPayload
err := decoder.Decode(&t)
if err != nil
panic(err)
result := map[string]string
"original": *t.Input,
"spongebob": spongebob(*t.Input),
w.Header().Set("Content-Type", "application/json")
err = json.NewEncoder(w).Encode(result)
if err != nil
return
Our handler needs to take the JSON body of the request and parse it into a Go structure defined outside of this snippet. The result should then be constructed from other functions that convert the input string into a SpongeBob utterance. Again, none of the libraries here are third-party dependencies; they all come standard with Go. Here you can see the prevalence of error handling via error codes as well as operation with err
occupies a large part in real estate.
To start this service locally, let’s simply do the following:
Then we send a GET request to /health
:
$ curl -s http://localhost:8080/health
We receive a JSON response indicating that the service is up and healthy. That’s it—one file, with about 100 lines of actual code, and you have a Go RESTful microservice working!
Implementation of your Go service on Heroku
Running the service on your laptop is fine, I guess. But you know what would be really cool? Launching on the web, that’s what.
These days we have many options on how to host a service like this. You could build your own infrastructure using AWS or Azure, but that quickly becomes complicated and expensive. I’ve been turning to Heroku more and more lately. As a Platform as a Service (PaaS), it’s a low-cost option that allows me to quickly deploy applications to the cloud.
When I do testing and development, I use their Eco Dyno plan to get 1000 dyno hours per month for $5. To deploy basic applications to production, I use their Basic Dyno Plan, which costs no more than $7 per month.
For frameworks that Heroku supports, the process of deploying directly from your local computer to the web is quick and painless. After setting up the Heroku account, I install the Heroku CLI and log in from the command line.
You can create a new application directly through the CLI or you can use the web interface. I named my app the same as my GitHub repo: golang-text-demo
. We’ll come up with something more awesome before our IPO; but for now this will do.
To deploy our GitHub repo to Heroku, we first need to add a remote repository.
$ heroku git:remote -a golang-text-demo
This creates a new remote location in our GitHub repo, pointing it to the Heroku app we just created. Now, whenever we push our branch to that remote (git push heroku main
), will trigger a flurry of activity as Heroku gets up and running.
At the end, we add one file called go.mod
, which lists our app’s build dependencies (we don’t have any) and the build configuration for Heroku. Our file is short and sweet, simply setting the version of Go we want Heroku to use:
module golang-text-demo
go 1.22
When we press the Heroku remote, Heroku initializes all the necessary cloud resources. This may take a minute or two when you first deploy your app, but the results appear to be cached, reducing time on subsequent deployments.
When your application is successfully deployed, you’ll see output that looks similar to this:
This gives us the URL for our deployed Heroku application. sweet! With only one git push
commands, we deployed the Go microservice in the cloud and it is now available anywhere in the world. To interact with it, we simply issue the same curl command we did before, but use the Heroku app URL instead localhost
.
The Heroku CLI also gives us access to our application logs. It’s almost like working with the tools directly on your local computer. We just run heroku logs -tail
and we see the latest log lines from Heroku and our application right there in our terminal window.
Before we wrap up, let’s briefly highlight the impressive insights that can be gained about your application from the Heroku application dashboard. Of course, there are the obvious things you care about – like how much your resources cost or whether or not they’re working. But the metrics section gives you impressive details about your app’s performance in near real-time.
Someone better do something about these critical errors…
Conclusion
In this guide, we’ve explored why Go is a great choice for building a modern, efficient, low-dependency web service. We built a simple API service in Go and showed how to deploy our service using Heroku. As a PaaS, Heroku supports the operation of a wide range of services, not just Go.
Plus, you now have the tools you need to start your own Go journey. Don’t wait, go!