ð Comprehensive Go Web Frameworks Comparison: Gin, Echo, and BeeGo
âïļ Introduction
Recently, I have been looking to develop a web application for budget tracking for myself. I have been using Google Sheets to track my budget previously, but I would like to have something more advanced. So, I decided to develop a web application for this purpose.
While thinking about the budgeting web application, I decided to use Go as the primary programming language for it due to the small VPS on DigitalOcean where this app will be hosted and my personal preferences. After working with Go for a while, I think that it's the best language for me.
In this article, I will consider the most popular Go web frameworks and compare them to choose the best one for my project.
ð Comparison
Criteria | BeeGo | Gin | Echo |
---|---|---|---|
Framework simplicity | Simple and very similar to Django or Spring MVC | Very simple and minimalistic | Very simple and minimalistic |
Go minimalism | No, it has a lot of magic like Spring MVC, Django, or Rails | Yes, it has a minimalistic approach | Yes, it has a minimalistic approach |
Speed of development | Fast speed of development due to built-in templates, ORM, and other features like in Django | Lower speed of development compared to BeeGo due to minimalistic approach | Lower speed of development compared to BeeGo due to minimalistic approach |
Performance | Fast performance but lower than Gin or Echo | Very fast performance | Very fast performance, but lower than Gin |
Popularity & maintenance | 31.6K stars on GitHub, last commit 4 days ago. However, the documentation website is down and only backup is available | 78.8K stars on GitHub, last commit 1 day ago | 29.8K stars on GitHub, last commit 1 day ago |
Adoption of the framework | Low adoption (by ChatGPT) | High adoption | High adoption |
From the comparison table, I can say that Gin and Echo are very similar frameworks in terms of simplicity and minimalism. I worked with Gin in the past in one of my companies, and I can say that it's an excellent web framework for Go.
While BeeGo has a high speed of development, it follows principles of Spring MVC and Django, which is not the Go way. However, it provides a lot of features out of the box like built-in ORM, templates, and others, which are not provided by Gin or Echo by default.
So, I decided to develop small prototypes of web applications for better comparison of these frameworks.
ðĪŠ Prototypes of Web applications
Framework | GitHub | Description |
---|---|---|
BeeGo | Framework's own project structure which doesn't follow the Go way. Built-in ORM, templates, and other features like in Django. No DDD. | |
Echo | Go project structure with FX (DI) and DDD. No ORM, Pongo2 templates (similar to Django templates) | |
Gin | Go project structure with FX (DI) and DDD. No ORM, Go standard templates out of the box |
From the developed prototypes, I prefer Gin or Echo due to following the Go way project structure and minimalism. BeeGo has a lot of magic and doesn't follow the Go way, it provides its own project structure which is not okay for me. Also, it provides ORM out of the box, which I don't want to use due to the complexity of maintaining ORM-based projects in the long run.
So, I decided to go deeper with the frameworks comparison and consider HTML templating approaches for them, as I'm planning to render HTML on the server side and have a very simple frontend client.
ðĩâðŦ Challenges with template engines
Framework | Template Engine | Description |
---|---|---|
BeeGo | Custom template engine | The template engine is similar to Django or Spring MVC out of the box. It works well with template inheritance and other features |
Echo | No template engine out of the box | Echo doesn't provide any template engine out of the box. You need to use a third-party template engine like Pongo2 or others |
Gin | Go standard templates | Gin provides the Go standard template engine, which doesn't support template inheritance for two or more templates out of the box |
So, BeeGo has a good template engine, but I decided not to use it in my project. I need to choose between Echo and Gin. There is a diagram depicting what exactly I need from the template engine:
I would like to have a base HTML file "layout.html" from which child pages like "dashboard.html" and "report.html" should inherit. This is a very simple problem which has been solved numerous times, but not in Go standard templates ð.
For Echo, I decided to use the Pongo2 template engine, which is very similar to Django templates and provides template inheritance. However, my concern was with the "very similar to Django templates" part. I just don't need so many features. Go standard templates are very simple and minimalistic, which is exactly what I need. However, they didn't support template inheritance for two or more templates.
ð Workaround for Go standard templates
So, I decided to use Go standard templates for my project, and Gin has built-in support for them. Also, the Gin community provides a way to implement multiple template inheritance using the multitemplate library. This library is pretty good, but it doesn't provide an automatic way to load templates in the right order.
So, I decided to fix this problem in the Gin prototype project.
1func NewRenderer(cfg *config.Config) multitemplate.Renderer {
2 renderer := multitemplate.NewRenderer()
3
4 // Load all template types
5 layouts, _ := filepath.Glob(fmt.Sprintf("%s/layouts/*.html", cfg.TemplateFolder))
6 partials, _ := filepath.Glob(fmt.Sprintf("%s/partials/*.html", cfg.TemplateFolder))
7 components, _ := filepath.Glob(fmt.Sprintf("%s/components/**/*.html", cfg.TemplateFolder))
8 pages, _ := filepath.Glob(fmt.Sprintf("%s/pages/**/*.html", cfg.TemplateFolder))
9
10 // Generate template map
11 for _, page := range pages {
12 files := []string{page}
13 files = append(files, layouts...)
14 files = append(files, partials...)
15 files = append(files, components...)
16
17 name := strings.TrimPrefix(page, fmt.Sprintf("%s/pages/", cfg.TemplateFolder))
18 name = strings.TrimSuffix(name, ".html")
19
20 renderer.AddFromFiles(name, files...)
21 }
22
23 return renderer
24}
The code above loads all templates from the specified folders and generates a template map for Gin. The key here is to load templates in the right order and bind them to the page name, which allows rendering pages utilizing page inheritance - GitHub:
1c.HTML(http.StatusOK, "user/profile", gin.H{
2 "User": user,
3})
While this approach is not perfect, it's good enough for my project. I don't need to use third-party template engines, and I can use Go standard templates out of the box.
ð Conclusions
I decided to use Gin for my personal budget tracking web application because:
Minimalism and following the Go way
Performance
Standard Go templates support
High adoption and popularity of the Gin framework
Also, Echo looks very similar to Gin, but it requires using third-party template engines, which I don't want to use.