Golang for PuzzleNomic v2
After the successful release of PuzzleNomic v1, I began to consider creating a new version of the API using a different programming language. Additionally, I wondered how performance could be improved on the other side. After conducting some research, I chose Golang due to its unique features such as error handling, code execution, and static typing, among others. In this blog post, I will explain why and how I successfully migrated the API from PHP to Golang using the Fiber framework, including deploying it to a cloud server.
Why Golang ?
Firstly, Golang is known for its concurrency features, which can significantly boost the performance of your application. Golang also has a garbage collector that can handle memory management efficiently, making it ideal for applications with a large number of concurrent requests.
Another benefit of Golang is its static typing. This means that you can catch errors at compile-time instead of runtime, which can save you a lot of time and resources in the long run. Golang also has a built-in error handling mechanism that allows you to handle errors more efficiently.
What is Fiber ?
Definitely, it is not avocados or beans that we can say are rich in fiber. Golang Fiber is a web framework for building fast, flexible, and secure web applications in Golang. It is designed to be easy to use and offers a rich set of features that make it a popular choice for building modern web applications.
Fiber is built on top of fasthttp, a high-performance HTTP server library for Golang. This allows Fiber to achieve faster request processing times and lower memory usage compared to other web frameworks.
Some of the key features of Fiber include:
- Fast routing: Fiber has a blazing fast router that can handle thousands of routes per second.
- Middleware support: Fiber comes with a built-in middleware stack that makes it easy to add functionality such as logging, authentication, and more to your application.
- Error handling: Fiber has a built-in error handling mechanism that makes it easy to catch and handle errors in your application.
- WebSocket support: Fiber has built-in support for WebSockets, allowing you to easily add real-time functionality to your application.
- Static file serving: Fiber makes it easy to serve static files such as images, CSS, and JavaScript files.
- Templating: Fiber has built-in support for popular templating engines like Handlebars, allowing you to easily create dynamic views for your application.
Overall, Fiber is a powerful and flexible web framework that makes it easy to build fast, scalable, and secure web applications in Golang. Its rich set of features and easy-to-use API make it a popular choice for developers looking to build modern web applications.
Compiled vs Interpreted
A compiled language, such as Golang, is a programming language in which the source code is translated into machine code, which can be directly executed by a computer. This process is done using a compiler, which translates the entire source code into machine code before the program is executed. Once the program is compiled, it can be executed multiple times without needing to be recompiled. This approach can result in faster program execution since the machine code is optimized for the hardware.
On the other hand, an interpreted language is executed directly by an interpreter without being compiled into machine code. The interpreter reads each line of code and executes it on the fly, which can result in slower program execution compared to compiled languages. However, interpreted languages can be more flexible since they do not require compilation and can be run on multiple platforms without changes.
Golang is a compiled language, which means that the source code is compiled into machine code before it is executed. This allows Golang to achieve faster program execution times compared to interpreted languages like Python or Ruby. Additionally, Golang's compiled nature allows for easy deployment of the code as it can be packaged as a standalone binary without any dependencies.
In summary, compiled languages like Golang are compiled into machine code, which can result in faster program execution times, while interpreted languages are executed on the fly by an interpreter.
Go is Strongly Typed
Go enforces strong and static typing, meaning variables can only have a single type. A string
variable like "hello world" can not be changed to an int
, such as the number 3
.
One of the biggest benefits of strong typing is that errors can be caught at "compile time". In other words, bugs are more easily caught ahead of time because they are detected when the code is compiled before it even runs.
Contrast this with most interpreted languages, where the variable types are dynamic. Dynamic typing can lead to subtle bugs that are hard to detect. With interpreted languages, the code must be run (sometimes in production if you are unlucky 😨) to catch syntax and type errors.
How it is going ?
I learned a lot of things while developing the API using Golang. One of them is using structs. Here is an example of how it was done.
1. Struct
The next thing is how to use SQL queries with Golang, which is something new to me. Here is an example of how it was done using the Golang SQL package. https://pkg.go.dev/database/sql
2. SQL query
- row.Scan
- db.QueryRow
- db.Exec
Yes, the method for dealing with SELECT, INSERT, and UPDATE statements for SQL queries in Golang is very neat and simple. For example, if you want to fetch some data from a database, the query would look something like this:
db.QueryRow("YOUR QUERY")
3. Marshal and Unmarshal
It's not a military rank. The function json.Marshal()
takes input data and returns a byte array and an error. The byte array is the JSON-encoded representation of the input data, and the error tells you if there were any issues encountered while marshaling the data into JSON.
4. BodyParser()
This bodyparser parses the HTTP request body using the BodyParser()
method of the fiber
web framework and stores its contents in the reqBody
variable. It then checks for any errors encountered during parsing, and if there is an error, it is returned from the function.
5. Map and interfaces
This useful as empty map that can be used to store data related to a puzzle. The use of interface{}
as the value type means that the map can store any type of value. The specific type of value will be determined at runtime when the data is added to the map.
6. For loops
Yes, for
loops are very useful for checking or comparing an array of existing puzzles with a new one.
And more......
What need to improve ?
When things start to become complex and the codebase grows larger, I would consider using the Model-View-Controller (MVC) pattern for this API. This would help to keep things organized and the codebase cleaner, instead of dumping all the code into one file. Currently, the main.go
file is the only file containing the code.
Do you see the small preview on the right side? The code is still messy with "debug" things because it is still in development and it is code written by a beginner. Don't expect this to be code written by a Golang developer with 10 years of experience.
For the deployment part, I will cover it in the next blog post. This will include how to deploy this Golang API to a cloud server and a preview of how it is consumed by the frontend. However, I am also thinking about how Puzzlenomic could work if the frontend is built with native Android language like Java , Kotlin or another hybrid framework like Flutter. I enjoy doing these kinds of things because I get bored with my everyday job and want to try something new and more challenging.