In the world of software development, APIs (Application Programming Interfaces) play a crucial role in facilitating communication between different systems and applications. When it comes to building APIs, developers have several options to choose from in terms of frameworks and libraries. Two popular options among Golang developers are Gin and Mux. Both Gin and Mux are open-source libraries that are widely used for building web applications and APIs. In this article, I will be explaining both Gin and Mux, comparing their features and functionality to help you decide which one is the best fit for your project. In this blog, I will explain an API made with the help of Gin Web Framework and then proceed with Mux. The API that, I will explain is a POST API. The creation of APIs with both frameworks would give you a clear picture of the differences between both frameworks. If you're interested in exploring these distinctions further and need expert guidance, consulting a specialized Golang company can be highly beneficial.
Essentials
To fully understand and follow along with this article, there are certain prerequisites that you should have a basic understanding of:
With a basic understanding of these prerequisites, you should be well-equipped to follow along and understand the concepts discussed in this blog.
Gin and Mux are both popular libraries for building web applications and APIs in Go. Here are some key differences between the two:
Gin is one of the quickest web frameworks for Go and is renowned for its outstanding performance. Mux, on the other hand, is more focused on usability and flexibility than on pure performance.
Gin's syntax is clearer and more expressive, making it simple to develop and understand code. Contrarily, Mux features a syntax that is more formal and lengthy, which might make it more challenging to comprehend and create code.
A middleware framework that is already present in Gin makes managing requests and responses simple. Mux needs the usage of additional middleware libraries since it lacks built-in middleware capability.
Gin supports group routing, which enables the prefix-based grouping of routes. Mux does not offer group routing, although it does support route matching depending on the request method and path.
Unexpected problems may be handled with ease because of Gin's built-in support for error management and recovery. Error handling is not supported natively by Mux; instead, additional libraries must be used.
Ultimately, the choice between Gin and Mux will depend on the specific needs of your project. Gin is a better choice for high-performance web applications and APIs, while Mux is better suited for projects that require more flexibility and ease of use. Now to develop more clarity on the concept, I will create a POST API using both frameworks and try to make you understand the differences practically.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package main
import (
"log"
"os"
"github.com/gin-gonic/gin"
"github.com/golangcompany/restfulapui/controllers"
)
func main() {
port := os.Getenv("PORT")
if port == "" {
port := "8080"
// }
router := gin.New()
router.Use(gin.Logger())
router.POST("/createuser", controllers.CreateUser())
log.Fatal(router.Run(":" + port))
}
}
Here, I will start with the main.go file and create a POST API with the help of Gin Web Framework. In the above code, the server listens on port 8080 and sets up a route for a POST request to the path "/createuser", which is handled by the "CreateUser" function from the "controllers" package. The router also uses logger middleware. The "log.Fatal" function is used to start the server and will exit the program with a non-zero exit code if there is an error starting the server.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package controllers
import (
"context"
"fmt"
"net/http"
"time"
"github.com/gin-gonic/gin"
"github.com/golangcompany/restfulapui/database"
"github.com/golangcompany/restfulapui/models"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"gopkg.in/mgo.v2/bson"
)
var UserCollection *mongo.Collection = database.UserData(database.Client, "User2")
func CreateUser() gin.HandlerFunc {
return func(c *gin.Context) {
var ctx, cancel = context.WithTimeout(context.Background(), 100*time.Second)
defer cancel()
var User models.User
if err := c.BindJSON(&User); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
c.Abort()
}
User.ID = primitive.NewObjectID()
_, inserterr := UserCollection.InsertOne(ctx, User)
if inserterr != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "not created"})
c.Abort()
}
c.IndentedJSON(200, "user created successfully")
}
}
Let us move ahead with the controllers file where I will create a createuser function that handles the creation of a new user in the system. It exports a function called CreateUser which returns a Gin handler function that is used to handle a POST request to the "/createuser" endpoint in the main function.
The function starts by defining a context with a timeout of 100 seconds and a Mongo collection for the user data. It then binds the JSON payload of the request to a models.User struct sets the ID of the user to a new Mongo Object ID and uses the InsertOne method to insert the user into the collection.
If the insert operation fails, it returns a JSON response with status code 500 and an error message. If it is successful, it returns a JSON response with status code 200 and a success message. It is using mongo driver for go in order to interact with the mongodb.
1
2
3
4
5
6
7
8
package models
Imports "go.mongodb.org/mongo-driver/bson/primitive"
type User struct {
Name string `json:"name" bson:"name"`
Age int `json:"age" bson:"age"`
}
Moving ahead with the struct, It has three fields:
The struct for the Mux framework will also remain the same, it's just the primitive, that I won’t be including in the project that I will build on Mux Framework in the coming sections.
In this section, I will create a POST API with the help of MUX Framework, that will give us a proper understanding of the difference between MUX and GIN practically. So let us begin with the “main.go” file first.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main
import (
"net/http"
"github.com/golangcompany/Gin-Mux/controller"
"github.com/gorilla/mux"
)
func main() {
r := mux.NewRouter()
r.HandleFunc("/createuser", controller.CreateUser).Methods("POST")
http.ListenAndServe(":8080", r)
}
In the above code, used the Gorilla Mux router to put up a web server. The "CreateUser" function from the "controller" package handles POST requests to the URL "/createuser," which is where the server listens on port 8080.
The CreateUser function from the controller package is responsible for handling the endpoint "/createuser," thus it registers a route for that endpoint and constructs a new Router using "mux.NewRouter()." Additionally, it states that this route should only accept "Methods("POST")" requests. The server is then launched by calling the "http.ListenAndServe" method with ":8080" to listen on and the router as the server handler.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package controller
import (
"context"
"encoding/json"
"net/http"
"strconv"
"github.com/golangcompany/Gin-Mux/database"
"github.com/golangcompany/Gin-Mux/models"
"github.com/gorilla/mux"
"go.mongodb.org/mongo-driver/mongo"
"gopkg.in/mgo.v2/bson"
)
var Collection *mongo.Collection = database.UserData(database.Client, "UserGinMux")
func CreateUser(w http.ResponseWriter, r *http.Request) {
decoder := json.NewDecoder(r.Body)
var user models.User
err := decoder.Decode(&user)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
_, err = Collection.InsertOne(context.TODO(), user)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
}
The creation of a new user in the system is handled by the controller code mentioned above. To handle incoming requests and responses, I have created a method named CreateUser that takes two parameters, "http.ResponseWriter" and "*http.Request."
The "JSON decoder" reads the request body. Next, it makes a copy of the "models. User " struct and decodes the request's JSON payload into it. If there is a problem decoding the request, it returns with a 400 Bad Request status code.
Following that, it uses the "InsertOne" function to add the user to a MongoDB collection. If something goes wrong, it sets the status code to 500 Internal Server Error and exits.
I hope you have noticed that both Gin and Mux are powerful frameworks for building web applications and APIs in Golang. Gin is known for its outstanding performance, clear and expressive syntax, built-in middleware, group routing, and built-in error management. Mux, on the other hand, is more focused on usability and flexibility. It does not have built-in middleware, group routing, or error management, but it is still a great option for projects that require more flexibility and ease of use.
I haven’t mentioned the process for database connection, If you are not aware of how to connect your application to the MongoDB database then you can follow my other blog “How to connect the Golang App with MongoDB”
In the end, the choice between Gin and Mux will depend on the specific needs of your project. If you're looking to build high-performance web applications and APIs, then Gin is the right choice for you. But if you're looking for more flexibility and ease of use, then Mux is the way to go. It is also important to note that both frameworks have their own set of pros and cons, and it's ultimately up to the developer to decide which one to use based on their specific use case and requirements.