Using Render and Go for the First Time
Check out how efficient it is to create a new API using Go, and then deploy it to the Render PaaS, both for the first time with zero DevOps.
Join the DZone community and get the full member experience.
Join For FreeMy ability to remember things can drive my wife crazy. Earlier this week, she asked me two questions after I finished telling her a story that I had recalled from my long-term memory:
How do you remember such things?
Why do you even remember that memory?
Honestly, I have no clue how to answer her questions, only that I recognized this ability earlier in my life. We both agreed that if there was a “useless trivia show,” I would be the world champion … hands down.
I feel like some events that I experience for the first time are often indexed in the long-term chambers of my brain, later becoming the source of my stories that I feel compelled to share with her. In terms of career implications, it does not take much effort to recall the first time I worked in a programming language or started using a service or framework.
Reading about the service provided by Render—one that promises “Zero DevOps”—made me want to take it for a test drive. Looking over the list of supported languages, I saw an opportunity to create a service in a programming language that is new to me.
As a result, I decided to give the Go programming language a shot, in hopes of adding a new deposit to my long-term memory bank.
The Magic 8-Ball Service
To make things fun, consider an example where Mattel asks for the creation of a RESTful API that mimics the Magic 8-Ball toy that was invented in 1946:
For those who are not aware, the Magic 8-Ball is a novelty item that performs basic fortune-telling tasks. With the 8-Ball image facing up, the person holding the ball asks a yes-no question, then turns it over to reveal an answer. The reply magically floats to the top out of the dark black ocean inside the toy.
The original design contained 20 unique answers, and the acceptance criteria is that only these responses will be allowed in the RESTful API:
Ten positive answers are noted with green bullets, and the remaining ten are an equal combination of non-committal (yellow) and negative (red) answers.
Consumers of the API simply need to make a standard GET request, which will return a random answer from the list of possible options. For validation purposes, Mattel would also like a second endpoint to retrieve a list of all available answers from this new service.
With my design, we can meet these requirements with the following endpoints:
GET
/answer
- randomly returns one of the twenty available answersGET
/answers
- returns a list of all twenty available answers
Getting Started With Go
While visiting the download page on the Go site, I noticed the installation process was very similar to getting started with the Java programming language. The installer used a wizard-like design where I basically just had to click buttons to navigate through the process. Once finished, I used the following terminal command to verify a successful installation:
╭─me@johnjvester ~
╰─$ go version
go version go1.17.6 darwin/amd64
Using IntelliJ IDEA, I added the Go plug-in and started a new project using the File | New | Project … command:
The project name of magic-eight-ball
just seemed right for this endeavor:
After some research, I found that the Gin web framework provides the functionality needed for a RESTful API written in Go, so I installed it with the following command:
$ go get -u github.com/gin-gonic/gin
To reference Gin inside my source code, I simply needed to include the following import:
import "github.com/gin-gonic/gin"
Now we are ready to start building the Magic 8-Ball API.
Creating the Magic 8-Ball API
The first thing I want to do is establish the data side of the API. For this example, the following JSON structure will make up the response body when an answer is provided:
{
"id" : number,
"response" : string
}
In Go, this JSON payload is defined (as shown below) and added to the main.go
file:
type response struct {
ID int `json:"id"`
Response string `json:"response"`
}
Since all of the data is static, I added the standard answers to the main.go
file:
var responses = []response{
{ID: 1, Response: "It is certain."},
{ID: 2, Response: "It is decidedly so."},
{ID: 3, Response: "Without a doubt."},
{ID: 4, Response: "Yes definitely."},
{ID: 5, Response: "You may rely on it."},
{ID: 6, Response: "As I see it, yes."},
{ID: 7, Response: "Most likely."},
{ID: 8, Response: "Outlook good."},
{ID: 9, Response: "Yes."},
{ID: 10, Response: "Signs point to yes."},
{ID: 11, Response: "Reply hazy, try again."},
{ID: 12, Response: "Ask again later."},
{ID: 13, Response: "Better not tell you now."},
{ID: 14, Response: "Cannot predict now."},
{ID: 15, Response: "Concentrate and ask again."},
{ID: 16, Response: "Don't count on it."},
{ID: 17, Response: "My reply is no."},
{ID: 18, Response: "My sources say no."},
{ID: 19, Response: "Outlook not so good."},
{ID: 20, Response: "Very doubtful."},
}
In order to leverage the responses variable, I added two functions to the main.go
file:
func getAllAnswers(c *gin.Context) {
c.IndentedJSON(http.StatusOK, responses)
}
func getRandomAnswer(c *gin.Context) {
rand.Seed(time.Now().Unix())
c.IndentedJSON(http.StatusOK, responses[rand.Intn(len(responses))])
}
The getAllAnswers()
function simply returns the responses list in JSON format, and the getRandomAnswer()
function randomly picks one of the twenty options and returns the value in JSON format.
Finally, the main()
function sets up the endpoints and the port used by the service:
func main() {
router := gin.Default()
router.GET("/answers", getAllAnswers)
router.GET("/answer", getRandomAnswer)
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
if err := router.Run(":" + port); err != nil {
log.Panicf("error: %s", err)
}
}
That’s all that is required to meet the acceptance criteria established by Mattel.
To start the application, we run the following command from the terminal:
╭─me@johnjvester ~/projects/jvc/go/magic-eight-ball
╰─$ go run .
The logs that displayed included those noted below:
[GIN-debug] GET /answers --> main.getAllAnswers (3 handlers)
[GIN-debug] GET /answer --> main.getRandomAnswer (3 handlers)
[GIN-debug] Listening and serving HTTP on :8080
I can test the API by sending curl requests with the following command:
╭─me@johnjvester ~
╰─$ curl http://localhost:8080/answer
This is the response I received:
{
"id": 6,
"response": "As I see it, yes."
}%
With the Go service running without any issues, I uploaded the code as a new project on GitLab:
https://gitlab.com/johnjvester/magic-eight-ball
Now I’m ready to see how Render works.
Deploying to Render Via GitLab
Getting started with Render was quick, easy, and free. I simply opted to use my GitLab credentials, which made things easy when selecting projects to deploy.
To get started, I selected the New button on the Render dashboard and chose the Web Service option:
I selected my magic-eight-ball
project on GitLab:
Within the Render platform, I decided to call my service jvc-magic-eight-ball
and kept the defaults for all of the other options:
Scrolling down, I opted to keep this service running on the free plan:
Then, I clicked the Create Web Service button. Within a few minutes, the Render dashboard showed me that my service was up and running:
I sent a request to the URL for my service on Render (https://jvc-magic-eight-ball.onrender.com/answer), and I received the following response:
{
"id": 5,
"response": "You may rely on it."
}
Within just a few clicks, I deployed my first RESTful API written in Go to the Render platform—and this didn’t incur any costs. More importantly, the Render approach did not require any DevOps skills or knowledge for me to complete my task.
Conclusion
The introduction of this article talked about my ability to retain and recall historical events several years (if not decades) later. The fact that this entire experiment took less than an hour of my time—from start to finish—is certainly worthy of becoming another one of those events.
Starting in 2021, I have been trying to live by the following mission statement, which I feel can apply to any IT professional:
“Focus your time on delivering features/functionality which extends the value of your intellectual property. Leverage frameworks, products, and services for everything else.”
- J. Vester
In this article, not only was I able to produce a functional API quickly with very little source code, but I was also able to deploy the project to a cloud provider simply by performing a series of small steps. Zero DevOps was promised, and Zero DevOps was delivered. This allowed me to focus my time on providing features to my customers.
If you are interested in the full source code, just navigate over to GitLab:
https://gitlab.com/johnjvester/magic-eight-ball
Knowing that I currently have APIs and applications running in the Heroku ecosystem, I plan to start looking into what a conversion from Heroku to Render looks like in the next few weeks. So far, I am quite impressed with what Render has to offer.
Have a really great day!
Opinions expressed by DZone contributors are their own.
Comments